commit 72ea2b578a49db9140f483500e0b97bae6269f4e Author: Will Nayes Date: Thu Mar 22 19:30:02 2018 -0500 Create macutils repository diff --git a/README b/README new file mode 100755 index 0000000..3968c9a --- /dev/null +++ b/README @@ -0,0 +1,483 @@ +This is version 2.0b3 of macutil (22-OCT-1992). + +This package contains the following utilities: + macunpack + hexbin + macsave + macstream + binhex + tomac + frommac + +Requirements: +a. Of course a C compiler. +b. A 32-bit machine with large memory (or at least the ability to 'malloc' + large chunks of memory). For reasons of efficiency and simplicity the + programs work 'in-core', also many files are first read in core. + If somebody can take the trouble to do it differently, go ahead! + There are also probably in a number of places implicit assumptions that + an int is 32 bits. If you encounter such occurrences feel free to + notify me. +c. A Unix (tm) machine, or something very close. There are probably quite + a lot of Unix dependencies. Also here, if you have replacements, feel + free to send comments. +d. This version normally uses the 'mkdir' system call available on BSD Unix + and some versions of SysV Unix. You can change that, see the makefile for + details. + +File name translation: + +The programs use a table driven program to do Mac filename -> Unix filename +translation. When compiled without further changes the translation is as +follows: + Printable ASCII characters except space and slash are not changed. + Slash and space are changed to underscore, as are all characters that + do not fall in the following group. + Accented letters are translated to their unaccented counterparts. +If your system supports the Latin-1 character set, you can change this +translation scheme by specifying '-DLATIN1' for the 'CF' macro in the +makefile. This will translate all accented letters (and some symbols) +to their Latin-1 counterpart. This feature is untested (I do not have +access to systems that cater for Latin-1), so use with care. +Future revisions of the program will have user settable conversions. + +Another feature of filename translation is that when the -DNODOT flag is +specified in the CF macro an initial period will be translated to underscore. + +MacBinary stream: + +Most programs allow MacBinary streams as either input or output. A +MacBinary stream is a series of files in MacBinary format pasted +together. Embedded within a MacBinary stream can be information about +folders. So a MacBinary stream can contain all information about a +folder and its constituents. + +Appleshare support: + +Optionally the package can be compiled for systems that support the sharing +of Unix and Mac filesystems. The package supports AUFS (AppleTalk Unix File +Server) from CAP (Columbia AppleTalk Package) and AppleDouble (from Apple). +It will not support both at the same time. Moreover this support requires +the existence of the 'mkdir' system call. And finally, as implemented it +probably will work on big-endian BSD compatible systems. If you have a SysV +system with restricted filename lengths you can get problems. I do not know +also whether the structures are stored native or Apple-wise on little-endian +systems. And also, I did not test it fully; having no access to either AUFS +or AppleDouble systems. + +Acknowledgements: +a. Macunpack is for a large part based on the utilities 'unpit' and 'unsit' + written by: + Allan G. Weber + weber%brand.usc.edu@oberon.usc.edu + (wondering whether that is still valid!). I combined the two into a + single program and did a lot of modification. For information on the + originals, see the files README.unpit and README.unsit. +b. The crc-calculating routines are based on a routine originally written by: + Mark G. Mendel + UUCP: ihnp4!umn-cs!hyper!mark + (this will not work anymore for sure!). Also here I modified the stuff + and expanded it, see the files README.crc and README.crc.orig. +c. LZW-decompression is taken from the sources of compress that are floating + around. Probably I did not use the most efficient version, but this + program was written to get it done. The version I based it on (4.0) is + authored by: + Steve Davies (decvax!vax135!petsd!peora!srd) + Jim McKie (decvax!mcvax!jim) (Hi Jim!) + Joe Orost (decvax!vax135!petsd!joe) + Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) + Ken Turkowski (decvax!decwrl!turtlevax!ken) + James A. Woods (decvax!ihnp4!ames!jaw) + I am sure those e-mail addresses also will not work! +d. Optional AUFS support comes from information supplied by: + Casper H.S. Dik + University of Amsterdam + Kruislaan 409 + 1098 SJ Amsterdam + Netherlands + + phone: +31205922022 + email: casper@fwi.uva.nl + This is an e-mail address that will workm but the address and phone + number ar no longer valid. + See the makefile. + Some caveats are applicable: + 1. I did not fully test it (we do not use it). But the unpacking + appears to be correct. Anyhow, as the people who initially compile + it and use it will be system administrators I am confident they are + able to locate bugs! (What if an archive contains a Macfile with + the name .finderinfo or .resource? I have had two inputs for AUFS + support [I took Caspers; his came first], but both do not deal with + that. Does CAP deal with it?) Also I have no idea whether this + version supports it under SysV, so beware. + 2. From one of the README's supplied by Casper: + Files will not appear in an active folder, because Aufs doesn't like + people working behind it's back. + Simply opening and closing the folder will suffice. + Appears to be the same problem as when you are unpacking or in some + other way creating files in a folder open to multifinder. I have seen + bundle bits disappear this way. So if after unpacking you see the + generic icon; check whether a different icon should appear and check + the bundle bit. + The desktop isn't updated, but that doesn't seem to matter. + I dunno, not using it. +e. Man pages are now supplied. The base was provided by: + Douglas Siebert + ISCA + dsiebert@icaen.uiowa.edu +f. Because of some problems the Uncompactor has been rewritten, it is now + based on sources from the dearchiver unzip (of PC fame). Apparently the + base code is by: + Samuel H. Smith + I have no further address available, but as soon as I find a better + attribution, I will include it. +g. UnstuffIt's LZAH code comes from lharc (also of PC fame) by: + Haruhiko Okumura, + Haruyasu Yoshizaki, + Yooichi Tagawa. +h. Zoom's code comes from information supplied by Jon W{tte + (d88-jwa@nada.kth.se). The Zoo decompressor is based on the routine + written by Rahul Dhesi (dhesi@cirrus.COM). This again is based on + code by Haruhiko Okumura. See also the file README.zoom. +i. MacLHa's decompressors are identical to the ones mentioned in g and h. +j. Most of hexbin's code is based on code written/modified by: + Dave Johnson, Brown University Computer Science + Darin Adler, TMQ Software + Jim Budler, amdcad!jimb + Dan LaLiberte, liberte@uiucdcs + ahm (?) + Jeff Meyer, John Fluke Company + Guido van Rossum, guido@cwi.nl (Hi!) + (most of the e-mail addresses will not work, the affiliation may also + be incorrect by now.) See also the file README.hexbin. +k. The dl code in hexbin comes is based on the original distribution of + SUMacC. +l. The mu code in hexbin is a slight modification of the hcx code (the + compressions are identical). +m. The MW code for StuffIt is loosely based on code by Daniel H. Bernstein + (brnstnd@acf10.nyu.edu). +n. Tomac and frommac are loosely based on the original macput and macget + by (the e-mail address will not work anymore): + Dave Johnson + ddj%brown@csnet-relay.arpa + Brown University Computer Science + +------------------------------------------------------------------------------- +Macunpack will unpack PackIt, StuffIt, Diamond, Compactor/Compact Pro, most +StuffItClassic/StuffItDeluxe, and all Zoom and LHarc/MacLHa archives, and +archives created by later versions of DiskDoubler. +Also it will decode files created by BinHex5.0, MacBinary, UMCP, +Compress It, ShrinkToFit, MacCompress, DiskDoubler and AutoDoubler. + +(PackIt, StuffIt, Diamond, Compactor, Compact/Pro, Zoom and LHarc/MacLHa are +archivers written by respectively: Harry R. Chesley, Raymond Lau, Denis Sersa, +Bill Goodman, Jon W{tte* and Kazuaki Ishizaki. BinHex 5.0, MacBinary and +UMCP are by respectively: Yves Lempereur, Gregory J. Smith, Information +Electronics. ShrinkToFit is by Roy T. Hashimoto, Compress It by Jerry +Whitnell, and MacCompress, DiskDoubler and AutoDoubler are all by +Lloyd Chambers.) + +* from his signature: + Jon W{tte - Yes, that's a brace - Damn Swede. +Actually it is an a with two dots above; some (German inclined) people +refer to it (incorrectly) as a-umlaut. + +It does not deal with: +a. Password protected archives. +b. Multi-segment archives. +c. Plugin methods for Zoom. +d. MacLHa archives not packed in MacBinary mode (the program deals very + poorly with that!). + +Background: +There are millions of ways to pack files, and unfortunately, all have been +implemented one way or the other. Below I will give some background +information about the packing schemes used by the different programs +mentioned above. But first some background about compression (I am no +expert, more comprehensive information can be found in for instance: +Tomothy Bell, Ian H. Witten and John G. Cleary, Modelling for Text +Compression, ACM Computing Surveys, Vol 21, No 4, Dec 1989, pp 557-591). + +Huffman encoding (also called Shannon-Fano coding or some other variation + of the name). An encoding where the length of the code for the symbols + depends on the frequency of the symbols. Frequent symbols have shorter + codes than infrequent symbols. The normal method is to first scan the + file to be compressed, and to assign codes when this is done (see for + instance: D. E. Knuth, the Art of Computer Programming). Later methods + have been designed to create the codes adaptively; for a survey see: + Jeremy S. Vetter, Design and Analysis of Dynamic Huffman Codes, JACM, + Vol 34, No 4, Oct 1987, pp 825-845. +LZ77: The first of two Ziv-Lempel methods. Using a window of past encoded + text, output consists of triples for each sequence of newly encoded + symbols: a back pointer and length of past text to be repeated and the + first symbol that is not part of that sequence. Later versions allowed + deviation from the strict alternation of pointers and uncoded symbols + (LZSS by Bell). Later Brent included Huffman coding of the pointers + (LZH). +LZ78: While LZ77 uses a window of already encoded text as a dictionary, + LZ78 dynamically builds the dictionary. Here again pointers are strictly + alternated with unencoded new symbols. Later Welch (LZW) managed to + eliminate the output of unencoded symbols. This algorithm is about + the same as the one independently invented by Miller and Wegman (MW). + A problem with these two schemes is that they are patented. Thomas + modified LZW to LZC (as used in the Unix compress command). While LZ78 + and LZW become static once the dictionary is full, LZC has possibilities + to reset the dictionary. Many LZC variants are in use, depending on the + size of memory available. They are distinguished by the maximum number + of bits that are used in a code. +A number of other schemes are proposed and occasionally used. The main +advantage of the LZ type schemes is that (especially) decoding is fairly fast. + +Programs background: + +Plain programs: +BinHex 5.0: + Unlike what its name suggest this is not a true successor of BinHex 4.0. + BinHex 5.0 takes the MacBinary form of a file and stores it in the data + fork of the newly created file. + Although BinHex 5.0 does not create BinHex 4.0 compatible files, StuffIt + will give the creator type of BinHex 5.0 (BnHq) to its binhexed files, + rather than the creator type of BinHex 4.0 (BNHQ). The program knows + about that. +MacBinary: + As its name suggests, it does the same as BinHex 5.0. +UMCP: + Looks similar, but the file as stored by UMCP is not true MacBinary. + Size fields are modified, the result is not padded to a multiple of 128, + etc. Macunpack deals with all that, but until now is not able to + correctly restore the finder flags of the original file. Also, UMCP + created files have type "TEXT" and creator "ttxt", which can create a + bit of confusion. Macunpack will recognize these files only if the + creator has been modified to "UMcp". + +Compressors: +ShrinkToFit: + This program uses a Huffman code to compress. It has an option (default + checked for some reason), COMP, for which I do not yet know the + meaning. Compressing more than a single file in a single run results + in a failure for the second and subsequent files. +Compress It: + Also uses a Huffman code to compress. +MacCompress: + MacCompress has two modes of operation, the first mode is (confusingly) + MacCompress, the second mode is (again confusingly) UnixCompress. In + MacCompress mode both forks are compressed using the LZC algorithm. + In UnixCompress mode only the data fork is compressed, and some shuffling + of resources is performed. Upto now macunpack only deals with MacCompress + mode. The LZC variant MacCompress uses depends on memory availability. + 12 bit to 16 bit LZC can be used. + +Archivers: +ArcMac: + Nearly PC-Arc compatible. Arc knows 8 compression methods, I have seen + all of them used by ArcMac, except the LZW techniques. Here they are: + 1: No compression, shorter header + 2: No compression + 3: (packing) Run length encoding + 4: (squeezing) RLE followed by Huffman encoding + 5: (crunching) LZW + 6: (crunching) RLE followed by LZW + 7: (crunching) as the previous but with a different hash function + 8: (crunching) RLE followed by 12-bit LZC + 9: (squashing) 13-bit LZC +PackIt: + When archiving a file PackIt either stores the file uncompressed or + stores the file Huffman encoded. In the latter case both forks are + encoded using the same Huffman tree. +StuffIt and StuffIt Classic/Deluxe: + These have the ability to use different methods for the two forks of a + file. The following standard methods I do know about (the last three + are only used by the Classic/Deluxe version 2.0 of StuffIt): + 0: No compression + 1: Run length encoding + 2: 14-bit LZC compression + 3: Huffman encoding + 5: LZAH: like LZH, but the Huffman coding used is adaptive + 6: A Huffman encoding using a fixed (built-in) Huffman tree + 8: A MW encoding +Diamond: + Uses a LZ77 like frontend plus a Fraenkel-Klein like backend (see + Apostolico & Galil, Combinatorial Algorithms on Words, pages 169-183). +Compactor/Compact Pro: + Like StuffIt, different encodings are possible for data and resource fork. + Only two possible methods are used: + 0: Run length encoding + 1: RLE followed by some form of LZH +Zoom: + Data and resource fork are compressed with the same method. The standard + uses either no compression or some form of LZH +MacLHa: + Has two basic modes of operation, Mac mode and Normal mode. In Mac mode + the file is archived in MacBinary form. In normal mode only the forks + are archived. Normal mode should not be used (and can not be unpacked + by macunpack) as all information about data fork size/resource fork size, + type, creator etc. is lost. It knows quite a few methods, some are + probably only used in older versions, the only methods I have seen used + are -lh0-, -lh1- and -lh5-. Methods known by MacLHa: + -lz4-: No compression + -lz5-: LZSS + -lzs-: LZSS, another variant + -lh0-: No compression + -lh1-: LZAH (see StuffIt) + -lh2-: Another form of LZAH + -lh3-: A form of LZH, different from the next two + -lh4-: LZH with a 4096 byte buffer (as far as I can see the coding in + MacLHa is wrong) + -lh5-: LZH with a 8192 byte buffer +DiskDoubler: + The older version of DiskDoubler is compatible with MacCompress. It does + not create archives, it only compresses files. The newer version (since + 3.0) does both archiving and compression. The older version uses LZC as + its compression algorithm, the newer version knows a number of different + compression algorithms. Many (all?) are algorithms used in other + archivers. Probably this is done to simplify conversion from other formats + to DiskDoubler format archives. I have seen actual DiskDoubler archives + that used methods 0, 1 and 8: + 0: No compression + 1: LZC + 2: unknown + 3: RLE + 4: Huffman (or no compression) + 5: unknown + 6: unknown + 7: An improved form of LZSS + 8: Compactor/Compact Pro compatible RLE/LZH or RLE only + 9: unknown + The DiskDoubler archive format contains many subtle twists that make it + difficult to properly read the archive (or perhaps this is on purpose?). + +Naming: +Some people have complained about the name conflict with the unpack utility +that is already available on Sys V boxes. I had forgotten it, so there +really was a problem. The best way to solve it was to trash pack/unpack/pcat +and replace it by compress/uncompress/zcat. Sure, man uses it; but man uses +pcat, so you can retain pcat. If that was not an option you were able to feel +free to rename the program. But finally I relented. It is now macunpack. + +When you have problems unpacking an archive feel free to ask for information. +I am especially keen when the program detects an unknown method. If you +encounter such an archive, please, mail a 'binhexed' copy of the archive +to me so that I can deal with it. Password protected archives are (as +already stated) not implemented. I do not have much inclination to do that. +Also I feel no inclination to do multi-segment archives. + +------------------------------------------------------------------------------- +Hexbin will de-hexify files created in BinHex 4.0 compatible format (hqx) +but also the older format (dl, hex and hcx). Moreover it will uudecode +files uuencoded by UUTool (the only program I know that does UU hexification +of all Mac file information). + +There are currently many programs that are able to create files in BinHex 4.0 +compatible format. There are however some slight differences, and most +de-hexifiers are not able to deal with all the variations. This program is +very simple minded. First it will intuit (based on the input) whether the +file is in dl, hex, hcx or hqx format. Next it will de-hexify the file. +When the format is hqx, it will check whether more files follow, and continue +processing. So you can catenate multiple (hqx) hexified files together and +feed them as a single file to hexbin. Also hexbin does not mind whether lines +are separated by CR's, LF's or combinations of the two. Moreover, it will +strip all leading, trailing and intermediate garbage introduced by mailers +etc. Next, it does not mind if a file is not terminated by a CR or an LF +(as StuffIt 1.5.1 and earlier did), but in that case a second file is not +allowed to follow it. Last, while most hexifiers output lines of equal length, +some do not. Hexbin will deal with that, but there are some caveats; see the +-c option in the man page. + +Background: + +dl format: + This was the first hexified format used. Programs to deal with it came + from SUMacC. This format only coded resource forks, 4 bits in a byte. +hex format: + I think this is the first format from Yves Lempereur. Like dl format, + it codes 4 bits in a byte, but is able to code both resource and + data fork. Is it BinHex 2.0? +hcx format: + A compressing variant of hex format. Codes 6 bits in a byte. + Is it BinHex 3.0? +hqx format: + Like hcx, but using a different coding (possibly to allow for ASCII->EBCDIC + and EBCDIC->ASCII translation, which not always results in an identical + file). Moreover this format also encodes the original Mac filename. +mu format: + The conversion can be done by the UUTool program from Octavian Micro + Development. It encodes both forks and also some finder info. You will + in general not use this with uudecode on non Mac systems, with uudecode + only the data fork will be uudecoded. UU hexification is well known (and + fairly old) in Unix environments. Moreover it has been ported to lots of + other systems. +------------------------------------------------------------------------------- +Macsave reads a MacBinary stream from standard input and writes the +files according to the options. +------------------------------------------------------------------------------- +Macstream reads files from the Unix host and will output a MacBinary stream +containing all those files together with information about the directory +structure. +------------------------------------------------------------------------------- +Binhex will read a MacBinary stream, or will read files/directories as +indicated on the command line, and will output all files in binhexed (.hqx) +format. Information about the directory structure is lost. +------------------------------------------------------------------------------- +Tomac will transmit a MacBinary stream, or named files to the Mac using +the XMODEM protocol. +------------------------------------------------------------------------------- +Frommac will receive one or more files from the Mac using the XMODEM protocol. +------------------------------------------------------------------------------- +This is an ongoing project, more stuff will appear. + +All comments are still welcome. Thanks for the comments I already received. + +dik t. winter, amsterdam, nederland +email: dik@cwi.nl + +-- +Note: +In these programs all algorithms are implemented based on publicly available +software to prevent any claim that would prevent redistribution due to +Copyright. Although parts of the code would indeed fall under the Copyright +by the original author, use and redistribution of all such code is explicitly +allowed. For some parts of it the GNU software license does apply. +-- +Appendix. + +BinHex 4.0 compatible file creators: + +Type Creator Created by + +"TEXT" "BthX" BinHqx +"TEXT" "BNHQ" BinHex +"TEXT" "BnHq" StuffIt and StuffIt Classic +"TEXT" "ttxt" Compactor + +Files recognized by macunpack: + +Type Creator Recognized as + +"APPL" "DSEA" "DiskDoubler" Self extracting +"APPL" "EXTR" "Compactor" Self extracting +"APPL" "Mooz" "Zoom" Self extracting +"APPL" "Pack" "Diamond" Self extracting +"APPL" "arc@" "ArcMac" Self extracting (not yet) +"APPL" "aust" "StuffIt" Self extracting +"ArCv" "TrAS" "AutoSqueeze" (not yet) +"COMP" "STF " "ShrinkToFit" +"DD01" "DDAP" "DiskDoubler" +"DDAR" "DDAP" "DiskDoubler" +"DDF." "DDAP" "DiskDoubler" (any fourth character) +"DDf." "DDAP" "DiskDoubler" (any fourth character) +"LARC" "LARC" "MacLHa (LHARC)" +"LHA " "LARC" "MacLHa (LHA)" +"PACT" "CPCT" "Compactor" +"PIT " "PIT " "PackIt" +"Pack" "Pack" "Diamond" +"SIT!" "SIT!" "StuffIt" +"SITD" "SIT!" "StuffIt Deluxe" +"Smal" "Jdw " "Compress It" +"TEXT" "BnHq" "BinHex 5.0" +"TEXT" "GJBU" "MacBinary 1.0" +"TEXT" "UMcp" "UMCP" +"ZIVM" "LZIV" "MacCompress(M)" +"ZIVU" "LZIV" "MacCompress(U)" (not yet) +"mArc" "arc*" "ArcMac" (not yet) +"zooM" "zooM" "Zoom" + diff --git a/binhex/binhex.c b/binhex/binhex.c new file mode 100755 index 0000000..4e58d98 --- /dev/null +++ b/binhex/binhex.c @@ -0,0 +1,174 @@ +#include +#include "../fileio/machdr.h" +#include "../fileio/rdfile.h" +#include "../util/patchlevel.h" + +extern char *malloc(); +extern char *realloc(); +extern char *strcat(); +extern void exit(); +extern void transname(); +extern void do_indent(); +extern void dofile(); + +#define LOCALOPT "RilqVH" + +static void usage(); + +static char options[128]; +static char *dir_stack; +static int dir_ptr = -64; +static int dir_max; +int dorep = 1; + +int main(argc, argv) +int argc; +char **argv; +{ + int c, i, j, n; + extern int optind; + extern char *optarg; + int errflg; + char text[32], ftype[5], fauth[5]; + int dir_skip = 0, write_it, query = 0, list = 0, info_only = 0; + int indent = 0; + + (void)strcat(options, get_rdfileopt()); + (void)strcat(options, LOCALOPT); + errflg = 0; + + while((c = getopt(argc, argv, options)) != EOF) { + if(!rdfileopt((char)c)) { + switch(c) { + case 'R': + dorep = 0; + break; + case 'l': + list++; + break; + case 'q': + query++; + break; + case 'i': + info_only++; + break; + case '?': + errflg++; + break; + case 'H': + give_rdfileopt(); + (void)fprintf(stderr, "Binhex specific options:\n"); + (void)fprintf(stderr, "-r:\tdo not use run length encoding\n"); + (void)fprintf(stderr, + "-i:\tgive information only, do not write\n"); + (void)fprintf(stderr, "-l:\tgive listing\n"); + (void)fprintf(stderr, + "-q:\tquery for every file/folder before writing\n"); + (void)fprintf(stderr, + "-V:\tgive information about this version\n"); + (void)fprintf(stderr, "-H:\tthis message\n"); + (void)fprintf(stderr, "Default is silent writing\n"); + exit(0); + case 'V': + (void)fprintf(stderr, "Version %s, ", VERSION); + (void)fprintf(stderr, "patchlevel %d", PATCHLEVEL); + (void)fprintf(stderr, "%s.\n", get_minb()); + exit(0); + } + } + } + if(errflg) { + usage(); + exit(1); + } + + if(info_only || query) { + list++; + } + + setup(argc - optind, argv + optind); + while((i = nextfile()) != ISATEND) { + if(dir_skip) { + if(i == ISDIR) { + dir_skip++; + } else if(i == ENDDIR) { + dir_skip--; + } + continue; + } + + write_it = 1; + n = file_info[I_NAMEOFF] & 0x7f; + transname(file_info + I_NAMEOFF + 1, text, n); + if(i == ISFILE) { + transname(file_info + I_TYPEOFF, ftype, 4); + transname(file_info + I_AUTHOFF, fauth, 4); + } + if(list) { + if(i == ISFILE) { + do_indent(indent); + (void)fprintf(stderr, + "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld", + text, ftype, fauth, (long)data_size, (long)rsrc_size); + } else if(i == ISDIR) { + do_indent(indent); + dir_ptr += 64; + if(dir_ptr == dir_max) { + if(dir_max == 0) { + dir_stack = malloc(64); + } else { + dir_stack = realloc(dir_stack, (unsigned)dir_max + 64); + } + dir_max += 64; + if(dir_stack == NULL) { + (void)fprintf(stderr, "Insufficient memory\n"); + exit(1); + } + } + for(j = 0; j <= n; j++) { + dir_stack[dir_ptr + j] = text[j]; + } + (void)fprintf(stderr, "folder=\"%s\"", text); + indent++; + } else { + indent--; + do_indent(indent); + (void)fprintf(stderr, "leaving folder \"%s\"", + dir_stack + dir_ptr); + dir_ptr -= 64; + } + if(info_only) { + write_it = 0; + } + if(query) { + if(i != ENDDIR) { + write_it = do_query(); + } else { + (void)fputc('\n', stderr); + } + if(!write_it && i == ISDIR) { + dir_skip = 1; + indent--; + dir_ptr -= 64; + } + } else { + (void)fputc('\n', stderr); + } + } + + if(write_it) { + if(i == ISFILE) { + dofile(); + } + } + } + exit(0); + /* NOTREACHED */ +} + +static void usage() +{ + (void)fprintf(stderr, "Usage: binhex [-%s] [files]\n", options); + (void)fprintf(stderr, "Use \"binhex -H\" for help.\n"); +} + diff --git a/binhex/dofile.c b/binhex/dofile.c new file mode 100755 index 0000000..599127a --- /dev/null +++ b/binhex/dofile.c @@ -0,0 +1,192 @@ +#include "../fileio/machdr.h" +#include "../fileio/rdfile.h" + +extern int dorep; +extern unsigned long binhex_crcinit; +extern unsigned long binhex_updcrc(); + +#define RUNCHAR 0x90 + +static int pos_ptr; +static char codes[] = + "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr"; +static int state; +static int savebits; +static int rep_char; +static int rep_count; + +void doheader(); +void dofork(); +void outbyte(); +void finish(); +void outbyte1(); +void out6bit(); +void outchar(); + +void dofile() +{ + (void)printf("(This file must be converted; you knew that already.)\n"); + (void)printf("\n"); + pos_ptr = 1; + state = 0; + rep_char = -1; + rep_count = 0; + outchar(':'); + doheader(); + dofork(data_fork, data_size); + dofork(rsrc_fork, rsrc_size); + finish(); + (void)putchar(':'); + (void)putchar('\n'); +} + +void doheader() +{ +unsigned long crc; +int i, n; + + crc = binhex_crcinit; + n = file_info[I_NAMEOFF]; + crc = binhex_updcrc(crc, file_info + I_NAMEOFF, n + 1); + for(i = 0; i <= n; i++) { + outbyte(file_info[I_NAMEOFF + i]); + } + n = 0; + crc = binhex_updcrc(crc, (char *)&n, 1); + outbyte(0); + crc = binhex_updcrc(crc, file_info + I_TYPEOFF, 4); + for(i = 0; i < 4; i++) { + outbyte(file_info[I_TYPEOFF + i]); + } + crc = binhex_updcrc(crc, file_info + I_AUTHOFF, 4); + for(i = 0; i < 4; i++) { + outbyte(file_info[I_AUTHOFF + i]); + } + crc = binhex_updcrc(crc, file_info + I_FLAGOFF, 2); + for(i = 0; i < 2; i++) { + outbyte(file_info[I_FLAGOFF + i]); + } + crc = binhex_updcrc(crc, file_info + I_DLENOFF, 4); + for(i = 0; i < 4; i++) { + outbyte(file_info[I_DLENOFF + i]); + } + crc = binhex_updcrc(crc, file_info + I_RLENOFF, 4); + for(i = 0; i < 4; i++) { + outbyte(file_info[I_RLENOFF + i]); + } + outbyte((int)(crc >> 8)); + outbyte((int)(crc & 0xff)); +} + +void dofork(fork, size) +char *fork; +int size; +{ +unsigned long crc; +int i; + + crc = binhex_updcrc(binhex_crcinit, fork, size); + for(i = 0; i < size; i++) { + outbyte(fork[i]); + } + outbyte((int)(crc >> 8)); + outbyte((int)(crc & 0xff)); +} + +void outbyte(b) +int b; +{ + b &= 0xff; + if(dorep && (b == rep_char)) { + if(++rep_count == 254) { + outbyte1(RUNCHAR); + outbyte1(255); + rep_char = -1; + rep_count = 0; + } + } else { + if(rep_count > 0) { + if(rep_count > 3) { + outbyte1(RUNCHAR); + outbyte1(rep_count + 1); + } else { + while(rep_count-- > 0) { + outbyte1(rep_char); + } + } + } + outbyte1(b); + if(b == RUNCHAR) { + outbyte1(0); + rep_char = -1; + } else { + rep_char = b; + } + rep_count = 0; + } +} + +void finish() +{ + if(rep_count > 0) { + if(rep_count > 3) { + outbyte1(RUNCHAR); + outbyte1(rep_count + 1); + } else { + while(rep_count-- > 0) { + outbyte1(rep_char); + } + } + } + switch(state) { + case 1: + out6bit(savebits << 4); + break; + case 2: + out6bit(savebits << 2); + break; + default: + break; + } +} + +void outbyte1(b) +int b; +{ + switch(state) { + case 0: + out6bit(b >> 2); + savebits = b & 0x3; + state = 1; + break; + case 1: + b |= (savebits << 8); + out6bit(b >> 4); + savebits = b & 0xf; + state = 2; + break; + case 2: + b |= (savebits << 8); + out6bit(b >> 6); + out6bit(b & 0x3f); + state = 0; + break; + } +} + +void out6bit(c) +char c; +{ + outchar(codes[c & 0x3f]); +} + +void outchar(c) +char c; +{ + (void)putchar(c); + if(++pos_ptr > 64) { + (void)putchar('\n'); + pos_ptr = 1; + } +} + diff --git a/binhex/makefile b/binhex/makefile new file mode 100755 index 0000000..f68ac7e --- /dev/null +++ b/binhex/makefile @@ -0,0 +1,51 @@ +CFLAGS = -O $(CF) + +SRCS = binhex.c dofile.c + +OBJS = binhex.o dofile.o + +LIB = ../crc/libcrc.a +TNAME = ../util/transname +BNAME = ../util/backtrans +UNAME = ../util/util +INAME = ../fileio/rdfile +GNAME = ../fileio/fileglob +XOBJS = $(TNAME).o $(BNAME).o $(UNAME).o $(INAME).o $(GNAME).o +XSRCS = $(TNAME).c $(BNAME).c $(UNAME).c $(INAME).c $(GNAME).c + +binhex: $(OBJS) $(XOBJS) $(LIB) + $(CC) $(CFLAGS) -o binhex $(OBJS) $(XOBJS) $(LIB) + +$(LIB): ../crc/makecrc.c + (cd ../crc; make CC=$(CC) CF="$(CF)" ) + +$(TNAME).o: $(TNAME).c + (cd ../util; make CC=$(CC) CF="$(CF)" ) + +$(BNAME).o: $(BNAME).c + (cd ../util; make CC=$(CC) CF="$(CF)" ) + +$(UNAME).o: $(UNAME).c + (cd ../util; make CC=$(CC) CF="$(CF)" ) + +$(INAME).o: $(INAME).c + (cd ../fileio; make CC=$(CC) CF="$(CF)" ) + +$(GNAME).o: $(GNAME).c + (cd ../fileio; make CC=$(CC) CF="$(CF)" ) + +lint: + lint $(CF) $(LFLAGS) $(SRCS) $(XSRCS) + +clean: + -rm -f *.o + +clobber:clean + -rm -f binhex + +binhex.o: ../fileio/machdr.h +binhex.o: ../fileio/rdfile.h +binhex.o: ../util/patchlevel.h +dofile.o: ../fileio/machdr.h +dofile.o: ../fileio/rdfile.h + diff --git a/comm/comm.h b/comm/comm.h new file mode 100755 index 0000000..715444e --- /dev/null +++ b/comm/comm.h @@ -0,0 +1,4 @@ +#define XM /* Know about XMODEM */ +#undef YM /* Know about YMODEM */ +#undef ZM /* Know about ZMODEM */ + diff --git a/comm/frommac.c b/comm/frommac.c new file mode 100755 index 0000000..41f346b --- /dev/null +++ b/comm/frommac.c @@ -0,0 +1,167 @@ +#include +#include "comm.h" +#include "../util/patchlevel.h" +#include "../fileio/machdr.h" +#include "globals.h" +#include "../fileio/fileglob.h" +#include "../fileio/wrfile.h" + +#define LOCALOPT "lmxyzoTVH" + +extern void exit(); +extern void setup_tty(); +extern void reset_tty(); + +extern char info[]; + +static void usage(); + +static char options[128]; +static int multi_file = 0; +static int listmode = 0; + +int main(argc, argv) +int argc; +char **argv; +{ + extern int optind; + extern char *optarg; + int errflg; + int c; + char tname[64]; + char fauth[5]; + char ftype[5]; + + set_wrfileopt(0); + (void)strcat(options, get_wrfileopt()); + (void)strcat(options, LOCALOPT); + errflg = 0; + + while((c = getopt(argc, argv, options)) != EOF) { + if(!wrfileopt((char)c)) { + switch(c) { + case 'l': + listmode++; + break; + case 'm': + multi_file++; + break; + case 'x': + xfertype = XMODEM; +#ifndef XM + (void)fprintf(stderr, "XMODEM not supported\n"); + exit(1); +#else /* XM */ + break; +#endif /* XM */ + case 'y': + xfertype = YMODEM; +#ifndef YM + (void)fprintf(stderr, "YMODEM not supported\n"); + exit(1); +#else /* YM */ + break; +#endif /* YM */ + case 'z': + xfertype = ZMODEM; +#ifndef ZM + (void)fprintf(stderr, "ZMODEM not supported\n"); + exit(1); +#else /* ZM */ + break; +#endif /* ZM */ + case 'o': + pre_beta++; + break; + case 'T': + time_out++; + break; + case '?': + errflg++; + break; + case 'H': + give_wrfileopt(); + (void)fprintf(stderr, "Frommac specific options:\n"); + (void)fprintf(stderr, "-l:\tgive listing\n"); + (void)fprintf(stderr, "-m:\tmulti-file transfer\n"); +#ifdef XM + (void)fprintf(stderr, "-x:\tuse XMODEM protocol\n"); +#endif /* XM */ +#ifdef YM + (void)fprintf(stderr, "-y:\tuse YMODEM protocol\n"); +#endif /* YM */ +#ifdef ZM + (void)fprintf(stderr, "-z:\tuse ZMODEM protocol\n"); +#endif /* ZM */ + (void)fprintf(stderr, "-o:\tuse pre-beta protocol\n"); + (void)fprintf(stderr, "-T:\tdetect time-outs\n"); + (void)fprintf(stderr, + "-V:\tgive information about this version\n"); + (void)fprintf(stderr, "-H:\tthis message\n"); + (void)fprintf(stderr, + "Default is silent receival of a single file using XMODEM\n"); + exit(0); + case 'V': + (void)fprintf(stderr, "Version %s, ", VERSION); + (void)fprintf(stderr, "patchlevel %d", PATCHLEVEL); + (void)fprintf(stderr, "%s.\n", get_mina()); + (void)fprintf(stderr, "Supported protocols:\n"); +#ifdef XM + (void)fprintf(stderr, "\tXMODEM\n"); +#endif /* XM */ +#ifdef YM + (void)fprintf(stderr, "\tYMODEM\n"); +#endif /* YM */ +#ifdef ZM + (void)fprintf(stderr, "\tZMODEM\n"); +#endif /* ZM */ + exit(0); + } + } + } + if(errflg) { + usage(); + exit(1); + } + + do { + setup_tty(); + switch(xfertype) { + case XMODEM: +#ifdef XM + xm_from(); + break; +#endif /* XM */ +#ifdef YM + case YMODEM: + ym_from(); + break; +#endif /* YM */ +#ifdef ZM + case ZMODEM: + zm_from(); + break; +#endif /* ZM */ + } + reset_tty(); + if(listmode) { + transname(info + I_NAMEOFF + 1, tname, info[I_NAMEOFF]); + transname(info + I_AUTHOFF, fauth, 4); + transname(info + I_TYPEOFF, ftype, 4); + (void)fprintf(stderr, + "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld", + tname, ftype, fauth, + get4(info + I_DLENOFF), get4(info + I_RLENOFF)); + (void)fprintf(stderr, "\n"); + } + } while(multi_file); + exit(0); + /* NOTREACHED */ +} + +static void usage() +{ + (void)fprintf(stderr, "Usage: frommac [-%s]\n", options); + (void)fprintf(stderr, "Use \"frommac -H\" for help.\n"); +} + diff --git a/comm/globals.c b/comm/globals.c new file mode 100755 index 0000000..4036814 --- /dev/null +++ b/comm/globals.c @@ -0,0 +1,6 @@ +#include "globals.h" + +int xfertype = XMODEM; +int pre_beta = 0; +int time_out = 0; + diff --git a/comm/globals.h b/comm/globals.h new file mode 100755 index 0000000..74b8c19 --- /dev/null +++ b/comm/globals.h @@ -0,0 +1,8 @@ +#define XMODEM 0 +#define YMODEM 1 +#define ZMODEM 2 + +extern int xfertype; +extern int pre_beta; +extern int time_out; + diff --git a/comm/makefile b/comm/makefile new file mode 100755 index 0000000..3298daf --- /dev/null +++ b/comm/makefile @@ -0,0 +1,91 @@ +CFLAGS = -O $(CF) + +SRCS1 = tomac.c xm_to.c ym_to.c zm_to.c tty.c globals.c +SRCS2 = frommac.c xm_from.c ym_from.c zm_from.c tty.c globals.c + +OBJS1 = tomac.o xm_to.o ym_to.o zm_to.o tty.o globals.o +OBJS2 = frommac.o xm_from.o ym_from.o zm_from.o tty.o globals.o + +LIB = ../crc/libcrc.a +TNAME = ../util/transname +BNAME = ../util/backtrans +UNAME = ../util/util +INAME = ../fileio/rdfile +ONAME = ../fileio/wrfile +GNAME = ../fileio/fileglob +XOBJS1 = $(TNAME).o $(BNAME).o $(UNAME).o $(INAME).o $(GNAME).o +XOBJS2 = $(TNAME).o $(UNAME).o $(ONAME).o $(GNAME).o +XSRCS1 = $(TNAME).c $(BNAME).c $(UNAME).c $(INAME).c $(GNAME).c +XSRCS2 = $(TNAME).c $(UNAME).c $(ONAME).c $(GNAME).c + +all: tomac frommac + touch all + +tomac: $(OBJS1) $(XOBJS1) + $(CC) $(CFLAGS) -o tomac $(OBJS1) $(XOBJS1) + +frommac: $(OBJS2) $(XOBJS2) + $(CC) $(CFLAGS) -o frommac $(OBJS2) $(XOBJS2) + +$(LIB): ../crc/makecrc.c + (cd ../crc; make CC=$(CC) CF="$(CF)" ) + +$(TNAME).o: $(TNAME).c + (cd ../util; make CC=$(CC) CF="$(CF)" ) + +$(BNAME).o: $(BNAME).c + (cd ../util; make CC=$(CC) CF="$(CF)" ) + +$(UNAME).o: $(UNAME).c + (cd ../util; make CC=$(CC) CF="$(CF)" ) + +$(INAME).o: $(INAME).c + (cd ../fileio; make CC=$(CC) CF="$(CF)" ) + +$(ONAME).o: $(ONAME).c + (cd ../fileio; make CC=$(CC) CF="$(CF)" ) + +$(GNAME).o: $(GNAME).c + (cd ../fileio; make CC=$(CC) CF="$(CF)" ) + +lint: + lint $(CF) $(LFLAGS) $(SRCS1) $(XSRCS) + +clean: + -rm -f *.o + +clobber:clean + -rm -f all tomac frommac + +tomac.o: comm.h +tomac.o: ../fileio/machdr.h +tomac.o: ../fileio/rdfile.h +tomac.o: ../util/patchlevel.h +tomac.o: globals.h +xm_to.o: comm.h +xm_to.o: ../fileio/machdr.h +xm_to.o: ../fileio/rdfile.h +xm_to.o: ../util/masks.h +xm_to.o: globals.h +xm_to.o: protocol.h +ym_to.o: comm.h +zm_to.o: comm.h +frommac.o: comm.h +frommac.o: ../util/patchlevel.h +frommac.o: ../fileio/machdr.h +frommac.o: globals.h +frommac.o: ../fileio/fileglob.h +frommac.o: ../fileio/wrfile.h +xm_from.o: comm.h +xm_from.o: ../fileio/machdr.h +xm_from.o: ../fileio/wrfile.h +xm_from.o: ../util/masks.h +xm_from.o: globals.h +xm_from.o: protocol.h +ym_from.o: comm.h +zm_from.o: comm.h +globals.o: globals.h +tty.o: ../util/masks.h +tty.o: protocol.h +tty.o: globals.h + diff --git a/comm/protocol.h b/comm/protocol.h new file mode 100755 index 0000000..a19b7e4 --- /dev/null +++ b/comm/protocol.h @@ -0,0 +1,22 @@ +#define RECORDBYTES 132 +#define DATABYTES 128 +#define NAMEBYTES 63 + +#define RETRIES 10 +#define SOHTIMO 10 +#define ACKTIMO 10 +#define LINTIMO 20 +#define CHRTIMO 2 + +#define MAXRECNO 0xff + +#define TMO -1 +#define DUP '\000' +#define SOH '\001' +#define EOT '\004' +#define ACK '\006' +#define NAK '\025' +#define CAN '\030' +#define EEF '\032' +#define ESC '\033' + diff --git a/comm/tomac.c b/comm/tomac.c new file mode 100755 index 0000000..dbc6a1d --- /dev/null +++ b/comm/tomac.c @@ -0,0 +1,242 @@ +#include +#include "comm.h" +#include "../fileio/machdr.h" +#include "../fileio/rdfile.h" +#include "../util/patchlevel.h" +#include "globals.h" + +extern char *malloc(); +extern char *realloc(); +extern char *strcat(); +extern void exit(); +extern void transname(); +extern void do_indent(); +extern void dofile(); +extern void setup_tty(); +extern void reset_tty(); + +#define LOCALOPT "ilqxyzoTVH" + +static void usage(); + +static char options[128]; +static char *dir_stack; +static int dir_ptr = -64; +static int dir_max; + +int main(argc, argv) +int argc; +char **argv; +{ + int c, i, j, n; + extern int optind; + extern char *optarg; + int errflg; + char text[32], ftype[5], fauth[5]; + int dir_skip = 0, write_it, query = 0, list = 0, info_only = 0; + int indent = 0; + + (void)strcat(options, get_rdfileopt()); + (void)strcat(options, LOCALOPT); + errflg = 0; + + while((c = getopt(argc, argv, options)) != EOF) { + if(!rdfileopt((char)c)) { + switch(c) { + case 'l': + list++; + break; + case 'q': + query++; + break; + case 'i': + info_only++; + break; + case 'o': + pre_beta++; + case 'x': + xfertype = XMODEM; +#ifndef XM + (void)fprintf(stderr, "XMODEM not supported\n"); + exit(1); +#else /* XM */ + break; +#endif /* XM */ + case 'y': + xfertype = YMODEM; +#ifndef YM + (void)fprintf(stderr, "YMODEM not supported\n"); + exit(1); +#else /* YM */ + break; +#endif /* YM */ + case 'z': + xfertype = ZMODEM; +#ifndef ZM + (void)fprintf(stderr, "ZMODEM not supported\n"); + exit(1); +#else /* ZM */ + break; +#endif /* ZM */ + case 'T': + time_out++; + break; + case '?': + errflg++; + break; + case 'H': + give_rdfileopt(); + (void)fprintf(stderr, "Tomac specific options:\n"); + (void)fprintf(stderr, + "-i:\tgive information only, do not write\n"); + (void)fprintf(stderr, "-l:\tgive listing\n"); + (void)fprintf(stderr, + "-q:\tquery for every file/folder before writing\n"); +#ifdef XM + (void)fprintf(stderr, "-x:\tuse XMODEM protocol\n"); +#endif /* XM */ +#ifdef YM + (void)fprintf(stderr, "-y:\tuse YMODEM protocol\n"); +#endif /* YM */ +#ifdef ZM + (void)fprintf(stderr, "-z:\tuse ZMODEM protocol\n"); +#endif /* ZM */ + (void)fprintf(stderr, "-o:\tuse pre-beta protocol\n"); + (void)fprintf(stderr, "-T:\tdetect time-outs\n"); + (void)fprintf(stderr, + "-V:\tgive information about this version\n"); + (void)fprintf(stderr, "-H:\tthis message\n"); + (void)fprintf(stderr, + "Default is silent sending with XMODEM\n"); + exit(0); + case 'V': + (void)fprintf(stderr, "Version %s, ", VERSION); + (void)fprintf(stderr, "patchlevel %d", PATCHLEVEL); + (void)fprintf(stderr, "%s.\n", get_minb()); + (void)fprintf(stderr, "Supported protocols:\n"); +#ifdef XM + (void)fprintf(stderr, "\tXMODEM\n"); +#endif /* XM */ +#ifdef YM + (void)fprintf(stderr, "\tYMODEM\n"); +#endif /* YM */ +#ifdef ZM + (void)fprintf(stderr, "\tZMODEM\n"); +#endif /* ZM */ + exit(0); + } + } + } + if(errflg) { + usage(); + exit(1); + } + + if(info_only || query) { + list++; + } + + setup(argc - optind, argv + optind); + while((i = nextfile()) != ISATEND) { + if(dir_skip) { + if(i == ISDIR) { + dir_skip++; + } else if(i == ENDDIR) { + dir_skip--; + } + continue; + } + + write_it = 1; + n = file_info[I_NAMEOFF] & 0x7f; + transname(file_info + I_NAMEOFF + 1, text, n); + if(i == ISFILE) { + transname(file_info + I_TYPEOFF, ftype, 4); + transname(file_info + I_AUTHOFF, fauth, 4); + } + if(list) { + if(i == ISFILE) { + do_indent(indent); + (void)fprintf(stderr, + "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld", + text, ftype, fauth, (long)data_size, (long)rsrc_size); + } else if(i == ISDIR) { + do_indent(indent); + dir_ptr += 64; + if(dir_ptr == dir_max) { + if(dir_max == 0) { + dir_stack = malloc(64); + } else { + dir_stack = realloc(dir_stack, (unsigned)dir_max + 64); + } + dir_max += 64; + if(dir_stack == NULL) { + (void)fprintf(stderr, "Insufficient memory\n"); + exit(1); + } + } + for(j = 0; j <= n; j++) { + dir_stack[dir_ptr + j] = text[j]; + } + (void)fprintf(stderr, "folder=\"%s\"", text); + indent++; + } else { + indent--; + do_indent(indent); + (void)fprintf(stderr, "leaving folder \"%s\"", + dir_stack + dir_ptr); + dir_ptr -= 64; + } + if(info_only) { + write_it = 0; + } + if(query) { + if(i != ENDDIR) { + write_it = do_query(); + } else { + (void)fputc('\n', stderr); + } + if(!write_it && i == ISDIR) { + dir_skip = 1; + indent--; + dir_ptr -= 64; + } + } else { + (void)fputc('\n', stderr); + } + } + + if(write_it) { + if(i == ISFILE) { + setup_tty(); + switch(xfertype) { +#ifdef XM + case XMODEM: + xm_to(); + break; +#endif /* XM */ +#ifdef YM + case YMODEM: + ym_to(); + break; +#endif /* YM */ +#ifdef ZM + case ZMODEM: + zm_to(); + break; +#endif /* ZM */ + } + reset_tty(); + } + } + } + exit(0); + /* NOTREACHED */ +} + +static void usage() +{ + (void)fprintf(stderr, "Usage: tomac [-%s] [files]\n", options); + (void)fprintf(stderr, "Use \"tomac -H\" for help.\n"); +} + diff --git a/comm/tty.c b/comm/tty.c new file mode 100755 index 0000000..38b0708 --- /dev/null +++ b/comm/tty.c @@ -0,0 +1,146 @@ +#include +#include +#ifndef TERMIOS_H +#include +#else /* TERMIOS_H */ +#include +#endif /* TERMIOS_H */ +#include +#include "../util/masks.h" +#include "protocol.h" +#include "globals.h" + +void cleanup(); +void timedout(); +int tgetc(); +void tputc(); + +static jmp_buf timobuf; + +#ifndef TERMIOS_H +static struct sgttyb otty, ntty; +#else /* TERMIOS_H */ +static struct termios otty, ntty; +#endif /* TERMIOS_H */ +static int ttyfd; +static int signal_set; + +void setup_tty() +{ + ttyfd = fileno(stderr); + if(!signal_set) { + (void)signal(SIGHUP, cleanup); + (void)signal(SIGINT, cleanup); + (void)signal(SIGQUIT, cleanup); + (void)signal(SIGTERM, cleanup); + if(time_out) { + (void)signal(SIGALRM, timedout); + } + signal_set = 1; + } +#ifndef TERMIOS_H + (void)ioctl(ttyfd, TIOCGETP, &otty); + ntty = otty; + ntty.sg_flags = RAW | ANYP; + (void)ioctl(ttyfd, TIOCSETP, &ntty); +#else /* TERMIOS_H */ + (void)tcgetattr(ttyfd, &otty); + ntty = otty; + ntty.c_lflag &= ~(ICANON | ISIG | ECHO); + ntty.c_iflag &= IXOFF; + ntty.c_oflag &= ~(OPOST); + ntty.c_cflag &= ~(PARENB | PARODD); + ntty.c_cc[VMIN] = 1; + ntty.c_cc[VTIME] = 0; + (void)tcsetattr(ttyfd, TCSAFLUSH, &ntty); +#endif /* TERMIOS_H */ +} + +void reset_tty() +{ + (void)sleep(1); /* Wait for output to drain */ +#ifndef TERMIOS_H + (void)ioctl(ttyfd, TIOCSETP, &otty); +#else /* TERMIOS_H */ + (void)tcsetattr(ttyfd, TCSAFLUSH, &otty); +#endif /* TERMIOS_H */ +} + +void cleanup(sig) int sig; +{ + reset_tty(); + exit(sig); +} + +void timedout() +{ + (void)signal(SIGALRM, timedout); + longjmp(timobuf, 1); +} + +int tgetc(timeout) +int timeout; +{ +char c; +int i; + + if(time_out) { + if(setjmp(timobuf)) { + return TMO; + } + (void)alarm(timeout); + } + i = read(ttyfd, &c, 1); + if(time_out) { + (void)alarm(0); + } + if(i == 0) { + return EOT; + } else { + return c & BYTEMASK; + } +} + +tgetrec(buf, count, timeout) +char *buf; +int count, timeout; +{ +int i, tot = 0, cc = count; + + if(time_out) { + if(setjmp(timobuf)) { + return TMO; + } + (void)alarm(timeout); + } + while(tot < count) { + i = read(ttyfd, buf, cc); + if(i < 0) { + continue; + } + tot += i; + cc -= i; + buf += i; + } + if(time_out) { + (void)alarm(0); + } + return 0; +} + +void tputc(c) +int c; +{ +char cc; + + cc = c & BYTEMASK; + (void)write(ttyfd, &cc, 1); +} + +void tputrec(buf, count) +char *buf; +int count; +{ + (void)write(ttyfd, buf, count); +} + diff --git a/comm/xm_from.c b/comm/xm_from.c new file mode 100755 index 0000000..d6e1af5 --- /dev/null +++ b/comm/xm_from.c @@ -0,0 +1,164 @@ +#include "comm.h" +#ifdef XM +#include +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "../util/masks.h" +#include "globals.h" +#include "protocol.h" + +extern int tgetc(); +extern int tgetrec(); +extern void tputc(); + +static void receive_part(); +static int receive_sync(); +static int receive_rec(); + +char info[INFOBYTES]; + +void xm_from() +{ +unsigned long data_size, rsrc_size; +char text[64]; + + if(receive_sync() == ACK) { + receive_part(info, DATABYTES, 1); + transname(info + I_NAMEOFF + 1, text, info[I_NAMEOFF]); + define_name(text); + data_size = get4(info + I_DLENOFF); + rsrc_size = get4(info + I_RLENOFF); + start_info(info, rsrc_size, data_size); + start_data(); + receive_part(out_buffer, data_size, 1); + start_rsrc(); + receive_part(out_buffer, rsrc_size, 0); + end_file(); + } +} + +static void receive_part(info, size, more) +char *info; +int size, more; +{ +int recno = 1, i, status, naks = 0; + + status = 0; + while(status != EOT) { + status = receive_rec(info, DATABYTES, recno); + switch(status) { + case EOT: + if(!pre_beta) { + tputc(ACK); + } + if(more) { + tputc(NAK); + } + size = 0; + break; + case ACK: + tputc(ACK); + naks = 0; + size -= DATABYTES; + info += DATABYTES; + recno = (recno + 1) & MAXRECNO; + break; + case DUP: + tputc(ACK); + naks = 0; + break; + case NAK: + if(naks++ < RETRIES) { + tputc(NAK); + break; + } + case CAN: + tputc(CAN); + cleanup(-1); + } + } +} + +static int receive_sync() +{ +int c; + + for(;;) { + c = tgetc(60); + switch(c) { + case ESC: + break; + case CAN: + cleanup(); + break; + case EOT: + case TMO: + return c; + default: + continue; + } + c = tgetc(1); + if(c == 'a') { + break;; + } + } + tputc(ACK); + return ACK; +} + +static int receive_rec(buf, bufsize, recno) +char *buf; +int bufsize, recno; +{ +int i, cksum, c, rec, recbar; +char *bp; + + c = tgetc(SOHTIMO); + switch(c) { + case EOT: + case CAN: + return c; + case SOH: + break; + case TMO: + default: + return NAK; + } + rec = tgetc(CHRTIMO); + if(rec == TMO) { + return NAK; + } + recbar = tgetc(CHRTIMO); + if(recbar == TMO) { + return NAK; + } + if(rec + recbar != MAXRECNO) { + return NAK; + } + if(tgetrec(buf, bufsize, LINTIMO) == TMO) { + return NAK; + } + bp = buf; + cksum = 0; + for(i = 0; i < bufsize; i++) { + cksum += *bp++ & BYTEMASK; + } + c = tgetc(CHRTIMO); + if(c == TMO) { + return NAK; + } + if(c != (cksum & BYTEMASK)) { + return NAK; + } + if(rec == recno - 1) { + return DUP; + } + if(rec != recno) { + return CAN; + } + return ACK; +} + +#else /* XM */ +int xm_from; /* Keep lint and some compilers happy */ +#endif /* XM */ diff --git a/comm/xm_to.c b/comm/xm_to.c new file mode 100755 index 0000000..868b82d --- /dev/null +++ b/comm/xm_to.c @@ -0,0 +1,98 @@ +#include "comm.h" +#ifdef XM +#include "../fileio/machdr.h" +#include "../fileio/rdfile.h" +#include "../util/masks.h" +#include "globals.h" +#include "protocol.h" + +extern int tgetc(); +extern void tputc(); +extern void tputrec(); + +static void send_part(); +static int send_sync(); +static void send_rec(); + +void xm_to() +{ + if(send_sync() == ACK) { + send_part(file_info, DATABYTES, 1); + send_part(data_fork, data_size, 1); + send_part(rsrc_fork, rsrc_size, 0); + } +} + +static void send_part(info, size, more) +char *info; +int size, more; +{ +int recno = 1, i, status; + + while(size > 0) { + for(i = 0; i < RETRIES; i++) { + send_rec(info, DATABYTES, recno); + status = tgetc(ACKTIMO); + if(status != NAK) { + break; + } + } + if(status == NAK || status == CAN) { + cleanup(-1); + } + size -= DATABYTES; + info += DATABYTES; + recno = (recno + 1) & MAXRECNO; + } + tputc(EOT); + if(!pre_beta) { + status = tgetc(ACKTIMO); + } + if(more) { + status = tgetc(ACKTIMO); + } +} + +static int send_sync() +{ +int c, i; + + for(i = 0; i < 3; i++) { + tputc(ESC); + tputc('a'); + while((c = tgetc(ACKTIMO)) != TMO) { + switch(c) { + case CAN: + case EOT: + case ACK: + return c; + default: + continue; + } + } + } + return CAN; +} + +static void send_rec(buf, bufsize, recno) +char *buf; +int bufsize, recno; +{ +int i, cksum; +char *bp; + + cksum = 0; + bp = buf; + for(i = 0; i < bufsize; i++) { + cksum += *bp++ & BYTEMASK; + } + tputc(SOH); + tputc((unsigned char)recno); + tputc((unsigned char)(MAXRECNO - recno)); + tputrec(buf, bufsize); + tputc((char)(cksum & BYTEMASK)); +} + +#else /* XM */ +int xm_to; /* Keep lint and some compilers happy */ +#endif /* XM */ diff --git a/comm/ym_from.c b/comm/ym_from.c new file mode 100755 index 0000000..9fd9d43 --- /dev/null +++ b/comm/ym_from.c @@ -0,0 +1,5 @@ +#include "comm.h" +#ifdef YM +#else /* YM */ +int ym_from; /* Keep lint and some compilers happy */ +#endif /* YM */ diff --git a/comm/ym_to.c b/comm/ym_to.c new file mode 100755 index 0000000..4e1277b --- /dev/null +++ b/comm/ym_to.c @@ -0,0 +1,5 @@ +#include "comm.h" +#ifdef YM +#else /* YM */ +int ym_to; /* Keep lint and some compilers happy */ +#endif /* YM */ diff --git a/comm/zm_from.c b/comm/zm_from.c new file mode 100755 index 0000000..74ceba7 --- /dev/null +++ b/comm/zm_from.c @@ -0,0 +1,5 @@ +#include "comm.h" +#ifdef ZM +#else /* ZM */ +int zm_from; /* Keep lint and some compilers happy */ +#endif /* ZM */ diff --git a/comm/zm_to.c b/comm/zm_to.c new file mode 100755 index 0000000..741dfce --- /dev/null +++ b/comm/zm_to.c @@ -0,0 +1,5 @@ +#include "comm.h" +#ifdef ZM +#else /* ZM */ +int zm_to; /* Keep lint and some compilers happy */ +#endif /* ZM */ diff --git a/crc/arc.c b/crc/arc.c new file mode 100644 index 0000000..58fbbec --- /dev/null +++ b/crc/arc.c @@ -0,0 +1,55 @@ +unsigned long arc_crcinit = 0; + +static unsigned short crctab[256] = { + 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, + 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, + 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, + 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, + 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, + 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, + 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, + 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, + 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, + 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, + 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, + 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, + 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, + 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, + 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, + 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, + 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, + 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, + 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, + 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, + 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, + 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, + 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, + 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, + 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, + 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, + 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, + 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, + 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, + 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, + 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, + 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040, +}; + +unsigned long arc_updcrc(icrc, icp, icnt) + unsigned long icrc; + unsigned char *icp; + int icnt; +{ +#define M1 0xff +#define M2 0xff00 + register unsigned long crc = icrc; + register unsigned char *cp = icp; + register int cnt = icnt; + + while(cnt--) { + crc=((crc>>8)&M1)^crctab[(crc&0xff)^*cp++]; + } + + return(crc); +} + diff --git a/crc/arc.o b/crc/arc.o new file mode 100644 index 0000000..d04cd0c Binary files /dev/null and b/crc/arc.o differ diff --git a/crc/binhex.c b/crc/binhex.c new file mode 100644 index 0000000..f73720d --- /dev/null +++ b/crc/binhex.c @@ -0,0 +1,55 @@ +unsigned long binhex_crcinit = 0; + +static unsigned short crctab[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0, +}; + +unsigned long binhex_updcrc(icrc, icp, icnt) + unsigned long icrc; + unsigned char *icp; + int icnt; +{ +#define M1 0xff +#define M2 0xff00 + register unsigned long crc = icrc; + register unsigned char *cp = icp; + register int cnt = icnt; + + while(cnt--) { + crc=((crc<<8)&M2)^crctab[((crc>>8)&0xff)^*cp++]; + } + + return(crc); +} + diff --git a/crc/binhex.o b/crc/binhex.o new file mode 100644 index 0000000..d883df3 Binary files /dev/null and b/crc/binhex.o differ diff --git a/crc/ccitt.c b/crc/ccitt.c new file mode 100644 index 0000000..cedd2ff --- /dev/null +++ b/crc/ccitt.c @@ -0,0 +1,55 @@ +unsigned long ccitt_crcinit = 65535; + +static unsigned short crctab[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0, +}; + +unsigned long ccitt_updcrc(icrc, icp, icnt) + unsigned long icrc; + unsigned char *icp; + int icnt; +{ +#define M1 0xff +#define M2 0xff00 + register unsigned long crc = icrc; + register unsigned char *cp = icp; + register int cnt = icnt; + + while(cnt--) { + crc=((crc<<8)&M2)^crctab[((crc>>8)&0xff)^*cp++]; + } + + return(crc); +} + diff --git a/crc/ccitt.o b/crc/ccitt.o new file mode 100644 index 0000000..1cd58c9 Binary files /dev/null and b/crc/ccitt.o differ diff --git a/crc/ccitt32.c b/crc/ccitt32.c new file mode 100644 index 0000000..170fbe2 --- /dev/null +++ b/crc/ccitt32.c @@ -0,0 +1,87 @@ +unsigned long ccitt32_crcinit = -1; + +static unsigned long crctab[256] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, + 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, + 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, + 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, + 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, + 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, + 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, + 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, + 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, + 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, + 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, + 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, + 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, + 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, + 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, + 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, + 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, + 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, + 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, + 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, + 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, + 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, + 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, + 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, + 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, + 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, + 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, + 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, + 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, + 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, + 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, + 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, + 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, + 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, + 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, + 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, + 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, + 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, + 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, + 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, + 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, + 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, + 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4, +}; + +unsigned long ccitt32_updcrc(icrc, icp, icnt) + unsigned long icrc; + unsigned char *icp; + int icnt; +{ +#define M1 0xffffff +#define M2 0xffffff00 + register unsigned long crc = icrc; + register unsigned char *cp = icp; + register int cnt = icnt; + + while(cnt--) { + crc=((crc<<8)&M2)^crctab[((crc>>24)&0xff)^*cp++]; + } + + return(crc); +} + diff --git a/crc/ccitt32.o b/crc/ccitt32.o new file mode 100644 index 0000000..0ae5b11 Binary files /dev/null and b/crc/ccitt32.o differ diff --git a/crc/kermit.c b/crc/kermit.c new file mode 100644 index 0000000..088a204 --- /dev/null +++ b/crc/kermit.c @@ -0,0 +1,55 @@ +unsigned long kermit_crcinit = 0; + +static unsigned short crctab[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78, +}; + +unsigned long kermit_updcrc(icrc, icp, icnt) + unsigned long icrc; + unsigned char *icp; + int icnt; +{ +#define M1 0xff +#define M2 0xff00 + register unsigned long crc = icrc; + register unsigned char *cp = icp; + register int cnt = icnt; + + while(cnt--) { + crc=((crc>>8)&M1)^crctab[(crc&0xff)^*cp++]; + } + + return(crc); +} + diff --git a/crc/kermit.o b/crc/kermit.o new file mode 100644 index 0000000..9b2f06a Binary files /dev/null and b/crc/kermit.o differ diff --git a/crc/libcrc.a b/crc/libcrc.a new file mode 100644 index 0000000..3188f64 Binary files /dev/null and b/crc/libcrc.a differ diff --git a/crc/makecrc b/crc/makecrc new file mode 100755 index 0000000..2600cbf Binary files /dev/null and b/crc/makecrc differ diff --git a/crc/makecrc.c b/crc/makecrc.c new file mode 100755 index 0000000..9112096 --- /dev/null +++ b/crc/makecrc.c @@ -0,0 +1,155 @@ +/* This program will write six C routines for the calculation of + * the following CRC's. */ + +/* The CRC polynomial. + * These 4 values define the crc-polynomial. + * If you change them, you must change crctab[]'s initial value to what is + * printed by initcrctab() [see 'compile with -DMAKETAB' above]. + */ + +/* This tables assumes CCITT is MSB first. Swapped means LSB first. In that + * case the polynomial is also swapped + */ + +/* 16 bit crc's */ +/* Value used by: CCITT KERMIT ARC BINHEX */ +/* the poly: 0x1021 0x8408 0xA001 0x1021 */ +/* original: 0x1021 0x1021 0x8005 0x1021 */ +/* init value: -1 0 0 0 */ +/* swapped: no yes yes no */ +/* bits in CRC: 16 16 16 16 */ +/* ARC used by LHARC, ZOO, STUFFIT */ +/* BINHEX used by XMODEM, PACKIT */ + +/* 32 bit crc's */ +/* Value used by: CCITT32 ZIP */ +/* the poly: 0x04c11db7 0xedb88320 */ +/* original: 0x04c11db7 0x04c11db7 */ +/* init value: -1 -1 */ +/* swapped no yes */ +/* bits in CRC: 32 32 */ +/* ZIP used by COMPACTOR */ + +#include + +extern void exit(); +extern char *strcat(); + +static void initcrctab(); + +main() +{ + initcrctab("ccitt", 0x1021, 0xffff, 0, 16); + initcrctab("kermit", 0x8408, 0, 1, 16); + initcrctab("arc", 0xa001, 0, 1, 16); + initcrctab("binhex", 0x1021, 0, 0, 16); + initcrctab("ccitt32",0x04c11db7,0xffffffff,0,32); + initcrctab("zip",0xedb88320,0xffffffff,1,32); + exit(0); + /*NOTREACHED*/ +} + +static void initcrctab(name, poly, init, swapped, bits) +char *name; +int poly, init, swapped, bits; +{ + register int b, i; + unsigned short v; + unsigned long vv; + FILE *fd; + char buf[20]; + + buf[0] = 0; + (void)strcat(buf, name); + (void)strcat(buf, ".c"); + if((fd = fopen(buf, "w")) == NULL) { + (void)fprintf(stderr, "Cannot open %s for writing\n", buf); + exit(1); + } + (void)fprintf(fd, "unsigned long %s_crcinit = %d;\n", name, init); + (void)fprintf(fd, "\n"); + if(bits == 16) { + (void)fprintf(fd, "static unsigned short crctab[256] = {\n"); + } else { + (void)fprintf(fd, "static unsigned long crctab[256] = {\n"); + } + (void)fprintf(fd, " "); + if(bits == 16) { + for(b = 0; b < 256; ++b) { + if(swapped) { + for(v = b, i = 8; --i >= 0;) + v = v & 1 ? (v>>1)^poly : v>>1; + } else { + for(v = b<<8, i = 8; --i >= 0;) + v = v & 0x8000 ? (v<<1)^poly : v<<1; + } + (void)fprintf(fd, "0x%.4x,", v & 0xffff); + if((b&7) == 7) { + (void)fprintf(fd, "\n"); + if(b != 255) (void)fprintf(fd, " "); + } else { + (void)fprintf(fd, " "); + } + } + } else { + for(b = 0; b < 256; ++b) { + if(swapped) { + for(vv = b, i = 8; --i >= 0;) + vv = vv & 1 ? (vv>>1)^poly : vv>>1; + } else { + for(vv = b<<24, i = 8; --i >= 0;) + vv = vv & 0x80000000 ? (vv<<1)^poly : vv<<1; + } + (void)fprintf(fd, "0x%.8x,", vv & 0xffffffff); + if((b&3) == 3) { + (void)fprintf(fd, "\n"); + if(b != 255) (void)fprintf(fd, " "); + } else { + (void)fprintf(fd, " "); + } + } + } + (void)fprintf(fd, "};\n"); + (void)fprintf(fd, "\n"); + (void)fprintf(fd, "unsigned long %s_updcrc(icrc, icp, icnt)\n", name); + (void)fprintf(fd, " unsigned long icrc;\n"); + (void)fprintf(fd, " unsigned char *icp;\n"); + (void)fprintf(fd, " int icnt;\n"); + (void)fprintf(fd, "{\n"); + if(bits == 16) { + (void)fprintf(fd, "#define M1 0xff\n"); + (void)fprintf(fd, "#define M2 0xff00\n"); + } else { + (void)fprintf(fd, "#define M1 0xffffff\n"); + (void)fprintf(fd, "#define M2 0xffffff00\n"); + } + (void)fprintf(fd, " register unsigned long crc = icrc;\n"); + (void)fprintf(fd, " register unsigned char *cp = icp;\n"); + (void)fprintf(fd, " register int cnt = icnt;\n"); + (void)fprintf(fd, "\n"); + (void)fprintf(fd, " while(cnt--) {\n"); + if(bits == 16) { + if (swapped) { + (void)fprintf(fd, + "\tcrc=((crc>>8)&M1)^crctab[(crc&0xff)^*cp++];\n"); + } else { + (void)fprintf(fd, + "\tcrc=((crc<<8)&M2)^crctab[((crc>>8)&0xff)^*cp++];\n"); + } + } else { + if(swapped) { + (void)fprintf(fd, + "\tcrc=((crc>>8)&M1)^crctab[(crc&0xff)^*cp++];\n"); + } else { + (void)fprintf(fd, + "\tcrc=((crc<<8)&M2)^crctab[((crc>>24)&0xff)^*cp++];\n"); + } + } + (void)fprintf(fd, " }\n"); + (void)fprintf(fd, "\n"); + (void)fprintf(fd, " return(crc);\n"); + (void)fprintf(fd, "}\n"); + (void)fprintf(fd, "\n"); + (void)fclose(fd); +} + diff --git a/crc/makecrc.o b/crc/makecrc.o new file mode 100644 index 0000000..40d1462 Binary files /dev/null and b/crc/makecrc.o differ diff --git a/crc/makefile b/crc/makefile new file mode 100755 index 0000000..0503869 --- /dev/null +++ b/crc/makefile @@ -0,0 +1,27 @@ +CFLAGS = -O $(CF) +CRCC = arc.c ccitt.c kermit.c binhex.c ccitt32.c zip.c +CRCO = arc.o ccitt.o kermit.o binhex.o ccitt32.o zip.o + +libcrc.a: $(CRCO) + ar r libcrc.a $(CRCO) + if test -f /usr/bin/ranlib ;\ + then \ + ranlib libcrc.a ;\ + fi + +clean: + -rm -f $(CRCC) $(CRCO) libcrc.a makecrc makecrc.o + +$(CRCC): makecrc + ./makecrc + +makecrc: makecrc.o + cc -O -o makecrc makecrc.o + +arc.o: arc.c +ccitt.o: ccitt.c +kermit.o: kermit.c +binhex.o: binhex.c +ccitt32.o: ccitt32.c +zip.o: zip.c + diff --git a/crc/zip.c b/crc/zip.c new file mode 100644 index 0000000..f7b98ef --- /dev/null +++ b/crc/zip.c @@ -0,0 +1,87 @@ +unsigned long zip_crcinit = -1; + +static unsigned long crctab[256] = { + 0x00000000, 0x09073096, 0x120e612c, 0x1b0951ba, + 0xff6dc419, 0xf66af48f, 0xed63a535, 0xe46495a3, + 0xfedb8832, 0xf7dcb8a4, 0xecd5e91e, 0xe5d2d988, + 0x01b64c2b, 0x08b17cbd, 0x13b82d07, 0x1abf1d91, + 0xfdb71064, 0xf4b020f2, 0xefb97148, 0xe6be41de, + 0x02dad47d, 0x0bdde4eb, 0x10d4b551, 0x19d385c7, + 0x036c9856, 0x0a6ba8c0, 0x1162f97a, 0x1865c9ec, + 0xfc015c4f, 0xf5066cd9, 0xee0f3d63, 0xe7080df5, + 0xfb6e20c8, 0xf269105e, 0xe96041e4, 0xe0677172, + 0x0403e4d1, 0x0d04d447, 0x160d85fd, 0x1f0ab56b, + 0x05b5a8fa, 0x0cb2986c, 0x17bbc9d6, 0x1ebcf940, + 0xfad86ce3, 0xf3df5c75, 0xe8d60dcf, 0xe1d13d59, + 0x06d930ac, 0x0fde003a, 0x14d75180, 0x1dd06116, + 0xf9b4f4b5, 0xf0b3c423, 0xebba9599, 0xe2bda50f, + 0xf802b89e, 0xf1058808, 0xea0cd9b2, 0xe30be924, + 0x076f7c87, 0x0e684c11, 0x15611dab, 0x1c662d3d, + 0xf6dc4190, 0xffdb7106, 0xe4d220bc, 0xedd5102a, + 0x09b18589, 0x00b6b51f, 0x1bbfe4a5, 0x12b8d433, + 0x0807c9a2, 0x0100f934, 0x1a09a88e, 0x130e9818, + 0xf76a0dbb, 0xfe6d3d2d, 0xe5646c97, 0xec635c01, + 0x0b6b51f4, 0x026c6162, 0x196530d8, 0x1062004e, + 0xf40695ed, 0xfd01a57b, 0xe608f4c1, 0xef0fc457, + 0xf5b0d9c6, 0xfcb7e950, 0xe7beb8ea, 0xeeb9887c, + 0x0add1ddf, 0x03da2d49, 0x18d37cf3, 0x11d44c65, + 0x0db26158, 0x04b551ce, 0x1fbc0074, 0x16bb30e2, + 0xf2dfa541, 0xfbd895d7, 0xe0d1c46d, 0xe9d6f4fb, + 0xf369e96a, 0xfa6ed9fc, 0xe1678846, 0xe860b8d0, + 0x0c042d73, 0x05031de5, 0x1e0a4c5f, 0x170d7cc9, + 0xf005713c, 0xf90241aa, 0xe20b1010, 0xeb0c2086, + 0x0f68b525, 0x066f85b3, 0x1d66d409, 0x1461e49f, + 0x0edef90e, 0x07d9c998, 0x1cd09822, 0x15d7a8b4, + 0xf1b33d17, 0xf8b40d81, 0xe3bd5c3b, 0xeaba6cad, + 0xedb88320, 0xe4bfb3b6, 0xffb6e20c, 0xf6b1d29a, + 0x12d54739, 0x1bd277af, 0x00db2615, 0x09dc1683, + 0x13630b12, 0x1a643b84, 0x016d6a3e, 0x086a5aa8, + 0xec0ecf0b, 0xe509ff9d, 0xfe00ae27, 0xf7079eb1, + 0x100f9344, 0x1908a3d2, 0x0201f268, 0x0b06c2fe, + 0xef62575d, 0xe66567cb, 0xfd6c3671, 0xf46b06e7, + 0xeed41b76, 0xe7d32be0, 0xfcda7a5a, 0xf5dd4acc, + 0x11b9df6f, 0x18beeff9, 0x03b7be43, 0x0ab08ed5, + 0x16d6a3e8, 0x1fd1937e, 0x04d8c2c4, 0x0ddff252, + 0xe9bb67f1, 0xe0bc5767, 0xfbb506dd, 0xf2b2364b, + 0xe80d2bda, 0xe10a1b4c, 0xfa034af6, 0xf3047a60, + 0x1760efc3, 0x1e67df55, 0x056e8eef, 0x0c69be79, + 0xeb61b38c, 0xe266831a, 0xf96fd2a0, 0xf068e236, + 0x140c7795, 0x1d0b4703, 0x060216b9, 0x0f05262f, + 0x15ba3bbe, 0x1cbd0b28, 0x07b45a92, 0x0eb36a04, + 0xead7ffa7, 0xe3d0cf31, 0xf8d99e8b, 0xf1deae1d, + 0x1b64c2b0, 0x1263f226, 0x096aa39c, 0x006d930a, + 0xe40906a9, 0xed0e363f, 0xf6076785, 0xff005713, + 0xe5bf4a82, 0xecb87a14, 0xf7b12bae, 0xfeb61b38, + 0x1ad28e9b, 0x13d5be0d, 0x08dcefb7, 0x01dbdf21, + 0xe6d3d2d4, 0xefd4e242, 0xf4ddb3f8, 0xfdda836e, + 0x19be16cd, 0x10b9265b, 0x0bb077e1, 0x02b74777, + 0x18085ae6, 0x110f6a70, 0x0a063bca, 0x03010b5c, + 0xe7659eff, 0xee62ae69, 0xf56bffd3, 0xfc6ccf45, + 0xe00ae278, 0xe90dd2ee, 0xf2048354, 0xfb03b3c2, + 0x1f672661, 0x166016f7, 0x0d69474d, 0x046e77db, + 0x1ed16a4a, 0x17d65adc, 0x0cdf0b66, 0x05d83bf0, + 0xe1bcae53, 0xe8bb9ec5, 0xf3b2cf7f, 0xfab5ffe9, + 0x1dbdf21c, 0x14bac28a, 0x0fb39330, 0x06b4a3a6, + 0xe2d03605, 0xebd70693, 0xf0de5729, 0xf9d967bf, + 0xe3667a2e, 0xea614ab8, 0xf1681b02, 0xf86f2b94, + 0x1c0bbe37, 0x150c8ea1, 0x0e05df1b, 0x0702ef8d, +}; + +unsigned long zip_updcrc(icrc, icp, icnt) + unsigned long icrc; + unsigned char *icp; + int icnt; +{ +#define M1 0xffffff +#define M2 0xffffff00 + register unsigned long crc = icrc; + register unsigned char *cp = icp; + register int cnt = icnt; + + while(cnt--) { + crc=((crc>>8)&M1)^crctab[(crc&0xff)^*cp++]; + } + + return(crc); +} + diff --git a/crc/zip.o b/crc/zip.o new file mode 100644 index 0000000..9164027 Binary files /dev/null and b/crc/zip.o differ diff --git a/doc/README.crc b/doc/README.crc new file mode 100755 index 0000000..6329232 --- /dev/null +++ b/doc/README.crc @@ -0,0 +1,7 @@ +This code is based on the code described in README.ORIG. +Changes are: +1. A program (makecrc) will create the different C source + files to do crc calculations. +2. The crc calculation method of binhex is added. +3. 32 bit crc's are added. + diff --git a/doc/README.crc.orig b/doc/README.crc.orig new file mode 100755 index 0000000..68a8d22 --- /dev/null +++ b/doc/README.crc.orig @@ -0,0 +1,193 @@ +/* updcrc(3), crc(1) - calculate crc polynomials + * + * Calculate, intelligently, the CRC of a dataset incrementally given a + * buffer full at a time. + * + * Usage: + * newcrc = updcrc( oldcrc, bufadr, buflen ) + * unsigned int oldcrc, buflen; + * char *bufadr; + * + * Compiling with -DTEST creates a program to print the CRC of stdin to stdout. + * Compile with -DMAKETAB to print values for crctab to stdout. If you change + * the CRC polynomial parameters, be sure to do this and change + * crctab's initial value. + * + * Notes: + * Regards the data stream as an integer whose MSB is the MSB of the first + * byte recieved. This number is 'divided' (using xor instead of subtraction) + * by the crc-polynomial P. + * XMODEM does things a little differently, essentially treating the LSB of + * the first data byte as the MSB of the integer. Define SWAPPED to make + * things behave in this manner. + * + * Author: Mark G. Mendel, 7/86 + * UUCP: ihnp4!umn-cs!hyper!mark, GEnie: mgm + */ + +/* The CRC polynomial. + * These 4 values define the crc-polynomial. + * If you change them, you must change crctab[]'s initial value to what is + * printed by initcrctab() [see 'compile with -DMAKETAB' above]. + */ + /* Value used by: CITT XMODEM ARC */ +#define P 0xA001 /* the poly: 0x1021 0x1021 A001 */ +#define INIT_CRC 0L /* init value: -1 0 0 */ +#define SWAPPED /* bit order: undef defined defined */ +#define W 16 /* bits in CRC:16 16 16 */ + + /* data type that holds a W-bit unsigned integer */ +#if W <= 16 +# define WTYPE unsigned short +#else +# define WTYPE unsigned long +#endif + + /* the number of bits per char: don't change it. */ +#define B 8 + +static WTYPE crctab[1<>(W-B)) ^ *cp++]; +#else + crc = (crc>>B) ^ crctab[(crc & ((1< +main() +{ + initcrctab(); +} + +initcrctab() +{ + register int b, i; + WTYPE v; + + + for( b = 0; b <= (1<= 0; ) + v = v & ((WTYPE)1<<(W-1)) ? (v<<1)^P : v<<1; +#else + for( v = b, i = B; --i >= 0; ) + v = v & 1 ? (v>>1)^P : v>>1; +#endif + crctab[b] = v; + + printf( "0x%lx,", v & ((1L< +#include + +#define MAXBUF 4096 + + + +main( ac, av ) + int ac; char **av; +{ + int fd; + int nr; + int i; + char buf[MAXBUF]; + WTYPE crc, crc2; + + fd = 0; + if( ac > 1 ) + if( (fd = open( av[1], O_RDONLY )) < 0 ) { + perror( av[1] ); + exit( -1 ); + } + crc = crc2 = INIT_CRC; + + while( (nr = read( fd, buf, MAXBUF )) > 0 ) { + crc = updcrc( crc, buf, nr ); + } + + if( nr != 0 ) + perror( "reading" ); + else { + printf( "%lx\n", crc ); + } + +#ifdef MAGICCHECK + /* tack one's complement of crc onto data stream, and + continue crc calculation. Should get a constant (magic number) + dependent only on P, not the data. + */ + crc2 = crc ^ -1L; + for( nr = W-B; nr >= 0; nr -= B ) { + buf[0] = (crc2 >> nr); + crc = updcrc(crc, buf, 1); + } + + /* crc should now equal magic */ + buf[0] = buf[1] = buf[2] = buf[3] = 0; + printf( "magic test: %lx =?= %lx\n", crc, updcrc(-1, buf, W/B)); +#endif MAGICCHECK +} + +#endif +**************************************************************************** + diff --git a/doc/README.hexbin b/doc/README.hexbin new file mode 100755 index 0000000..885fa17 --- /dev/null +++ b/doc/README.hexbin @@ -0,0 +1,31 @@ +The comment for the predecessor of hexbin. + +/* + * xbin -- unpack BinHex format file into suitable + * format for downloading with macput + * Dave Johnson, Brown University Computer Science + * + * (c) 1984 Brown University + * may be used but not sold without permission + * + * created ddj 12/16/84 + * revised ddj 03/10/85 -- version 4.0 compatibility, other minor mods + * revised ddj 03/11/85 -- strip LOCKED bit from m_flags + * revised ahm 03/12/85 -- System V compatibility + * revised dba 03/16/85 -- (Darin Adler, TMQ Software) 4.0 EOF fixed, + * 4.0 checksum added + * revised ddj 03/17/85 -- extend new features to older formats: -l, stdin + * revised ddj 03/24/85 -- check for filename truncation, allow multiple files + * revised ddj 03/26/85 -- fixed USG botches, many problems w/multiple files + * revised jcb 03/30/85 -- (Jim Budler, amdcad!jimb), revised for compatibility + * with 16-bit int machines + * revised dl 06/16/85 -- (Dan LaLiberte, liberte@uiucdcs) character + * translation speedup + * revised ddj 09/30/85 -- fixed problem with run of RUNCHAR + * revised gvr 11/15/86 -- speed-up: rewrote .hqx decoding (mcvax!guido) + * revised jwm 04/26/88 -- now recognizes "(Convert with" as a starting line + * -- the widely-used Stuffit uses this as a header + * revised dtw ../../89 -- hqx format will skip garbage lines; undoes some of + * -- gvr's work. will now also recognize .dl format. + */ + diff --git a/doc/README.macget b/doc/README.macget new file mode 100755 index 0000000..c3038d3 --- /dev/null +++ b/doc/README.macget @@ -0,0 +1,14 @@ +/* + * macget -- receive file from macintosh using xmodem protocol + * Dave Johnson, Brown University Computer Science + * + * (c) 1984 Brown University + * may be used but not sold without permission + * + * created ddj 5/22/84 + * revised ddj 6/29/84 -- added [-rdu] options + * revised ddj 7/16/84 -- protocol changes for MacTerminal Beta Version 0.5X + * revised ddj 7/31/84 -- pre-4.2 signal bugs fixed in timedout() + * revised ddj 11/7/84 -- renamed send_sync() -> get_sync() + * revised lra 1/01/87 -- multiple file uploads added (VersTerm compatible) + */ diff --git a/doc/README.macput b/doc/README.macput new file mode 100755 index 0000000..4d5acb2 --- /dev/null +++ b/doc/README.macput @@ -0,0 +1,18 @@ +/* + * + * Here is the source for the current incarnation of macput . . . . + * It is compatible with the 1.1 Release version of MacTerminal, + * though in case you still need to use the -0.15X version, there's + * the "-o" option to provide compatibility. Versions 0.5 and 0.9 + * have a bug in the record checksum calculation which will break + * file transfers, so 1.1 is recommended. + * + * Please pass any improvements/bug fixes on to me, and + * if you know of any good protocols for use on a flow-controlled + * line, let me know. + * + * Dave Johnson + * ddj%brown@csnet-relay.arpa + * Brown University Computer Science + * +*/ diff --git a/doc/README.scan b/doc/README.scan new file mode 100755 index 0000000..e730c4b --- /dev/null +++ b/doc/README.scan @@ -0,0 +1,92 @@ +Preliminary info about the Unix scanner. +---------------------------------------- + +This file states mostly how to use it, it is not yet full documentation. + +There are a few utilities in this package that help scanning: macidf, +macscan, macstream, hexbin and macunpack. I will give examples of use +where every use highlights some factilities. + +The main program is macscan. It reads from standard input (NB: no file +parameters) and will scan the input for offensive stuff. The input +consists of a stream of files in MacBinary format, with additional +information between (about Unix file name, Archive/Packed file name, +folder entry/exit in an archive etc.). + +To scan a single MacBinary file just do: + macscan + * + * The format of is a linked list of + * EntryInfo, where "next" points to the next logical address + * on disk. "next" as 0 means no more entries. + * + * For a directory, the "creator" field points to the + * first file/folder entry inside the directory. + * + * For a file, IF the "what" field is ZOOM_PLUGIN, + * the EntryInfo is followed by a length byte and that + * many characters naming the compression engine. + * Right after that (or right after the EntryInfo in the + * case of uncompressed files or default compressed files) + * follows the data fork compressed, followed by the + * resource fork compressed. + * + * Note that there is no "end of compressed data" marker; + * your compressor engine will have to figure that out by + * itself. You could for instance do an ftell before + * compressing; writing a (long)0 and then write your + * compressed data, seek back and write the actual length. + * + * Note that new entries always are added last in the file, + * so you need not worry about overrunning anything else. + */ + +/* + * The default compressor in Zoom is the same as used in + * "better" compression mode in ZOO 2.10. A Zoo extractor + * or convertor could parse the ZOO header format, and use + * the built-in engine for "lzh" compressed files. + * + * The simplest way to do this is to call SetEngine(-1) and + * call Encode / Decode. -1 is the default compressor, 0 is + * the null compressor (fork copy) + * + * Likewise, a UNIX zoom packer/unpacker could use the source + * for zoo 2.10 functions "lzh_encode" and "lzh_decode" + * (they're wrappers) for compression. + */ + +/* + * This "EntryInfo" is presently also a file header. + * Some fields may be non-obvious. Don't use these. + * For instance, "comment" is currently unsupported, + * and should be left as 0 + */ +#ifndef ZOOM_TYPES +typedef enum zoomWhatType { + ZOOM_NOTHING , ZOOM_FILE , ZOOM_UCFILE , ZOOM_DIR , ZOOM_PLUGIN +} ZoomWhatType ; +#define ZOOM_TYPES +#endif + +/* + * Remember to fill in "hlen" correctly as well. When reading a header, + * Zoom checks with this field to see if it should skip some more data + * or seek back a little, so as to make future field additions at the + * end possible. You should NOT add your own fields to this structure. + */ +typedef struct EntryInfo { + + /* "what" is a ZoomWhatType */ + char what ; /* Negative if deleted */ + unsigned char hlen ; /* Header length */ + unsigned short boolFlags ; /* Boolean flags */ + long next ; /* Next entry */ + + long complen ; /* Length of compressed data */ + long compdata ; /* Data fork portion of compressed data - for dirs, number of entries */ + long uclen ; /* Length of uncompressed entry */ + long ucdata ; /* Data fork part of uncompressed */ + + long type ; /* File type */ + long creator ; /* File creator - for dir, offset of file */ + long mdate ; /* Modification date */ + long comment ; /* Comment offset */ + short flags ; /* Macintosh file flags */ + + short dataCrc ; /* Data fork crc */ + short resCrc ; /* Resource fork crc */ + + unsigned char name [ 32 ] ; /* File/Dir name */ + +} EntryInfo ; + diff --git a/fileio/all b/fileio/all new file mode 100644 index 0000000..e69de29 diff --git a/fileio/appledouble.h b/fileio/appledouble.h new file mode 100755 index 0000000..c377a00 --- /dev/null +++ b/fileio/appledouble.h @@ -0,0 +1,53 @@ +#define FI_MAGIC 333319 +#define FI_VERSION 1 +#define FI_FILL5 5 +#define FI_FILL6 2 +#define FI_HLEN 589 +#define FI_FILL7 3 +#define FI_NAMPTR 86 +#define FI_FILL9 4 +#define FI_COMMPTR 341 +#define FI_FILL12 7 +#define FI_TIMEPTR 541 +#define FI_TIMESIZE 16 +#define FI_FILL15 9 +#define FI_INFOPTR 557 +#define FI_INFOSIZE 32 + +/* All as char[n] because of possible alignment problems. But is this needed? + Is this stuff in host order or in client order? Assuming client order for + the moment. Will not be a problem on big-endian machines. */ +typedef struct { + char fi_magic[4]; /* magic header */ + char fi_version[2]; /* version number */ + char fi_fill1[4]; /* = 0, ???? */ + char fi_fill2[4]; /* = 0, ???? */ + char fi_fill3[4]; /* = 0, ???? */ + char fi_fill4[4]; /* = 0, ???? */ + char fi_fill5[4]; /* = 5, ???? */ + char fi_fill6[4]; /* = 2, ???? */ + char fi_hlen[4]; /* = 589, header length */ + char fi_rsrc[4]; /* resource length */ + char fi_fill7[4]; /* = 3, ???? */ + char fi_namptr[4]; /* = 86, filename pointer */ + char fi_namlen[4]; /* Mac filename length */ + char fi_fill9[4]; /* = 4, ???? */ + char fi_commptr[4]; /* = 341, comment pointer */ + char fi_commsize[4]; /* = 0, comment size */ + char fi_fill12[4]; /* = 7, ???? */ + char fi_timeptr[4]; /* = 541, pointer to times */ + char fi_timesize[4]; /* = 16, size of times */ + char fi_fill15[4]; /* = 9, ???? */ + char fi_infoptr[4]; /* = 557, finder info pointer */ + char fi_infosize[4]; /* = 32, finder info size */ + char fi_name[255]; /* Macintosh filename */ + char fi_comment[200];/* = 0, Comment */ + char fi_ctime[4]; /* Creation time (Unix time) */ + char fi_mtime[4]; /* Modification time (Unix time) */ + char fi_fill19[4]; /* = 0, ???? */ + char fi_fill20[4]; /* = 0, ???? */ + char fi_type[4]; /* File type */ + char fi_auth[4]; /* File creator */ + char fi_finfo[24]; /* Finder info */ +} FileInfo; + diff --git a/fileio/aufs.h b/fileio/aufs.h new file mode 100755 index 0000000..f642deb --- /dev/null +++ b/fileio/aufs.h @@ -0,0 +1,33 @@ +#define MAXCLEN 199 /* max size of a comment string */ +#define FINFOLEN 32 /* Finder info is 32 bytes */ +#define MAXMACFLEN 31 /* max Mac file name length */ +#define FI_MAGIC1 255 +#define FI_VERSION 0x10 /* version major 1, minor 0 */ + /* if we have more than 8 versions wer're */ + /* doiong something wrong anyway */ +#define FI_MAGIC 0xda +#define FI_BM_SHORTFILENAME 0x1 /* is this included? */ +#define FI_BM_MACINTOSHFILENAME 0x2 /* is this included? */ +#define FI_MDATE 0x01 /* mtime & utime are valid */ +#define FI_CDATE 0x02 /* ctime is valid */ + +typedef struct { + char fi_fndr[FINFOLEN]; /* finder info */ + short fi_attr; /* attributes */ + char fi_magic1; /* addional magic word check */ + char fi_version; /* version number */ + char fi_magic; /* magic word check */ + char fi_bitmap; /* bitmap of included info */ + char fi_shortfilename[12+1]; /* possible short file name */ + char fi_macfilename[32+1]; /* possible macintosh file name */ + char fi_comln; /* comment length */ + char fi_comnt[MAXCLEN+1]; /* comment string */ +#ifdef AUFSPLUS + char fi_datemagic; /* sanity check */ + char fi_datevalid; /* validity flags */ + char fi_ctime[4]; /* mac file create time */ + char fi_mtime[4]; /* mac file modify time */ + char fi_utime[4]; /* (real) time mtime was set */ +#endif /* AUFSPLUS */ +} FileInfo; + diff --git a/fileio/fileglob.c b/fileio/fileglob.c new file mode 100755 index 0000000..979a488 --- /dev/null +++ b/fileio/fileglob.c @@ -0,0 +1,2 @@ +int bytes_read, bytes_written; + diff --git a/fileio/fileglob.h b/fileio/fileglob.h new file mode 100755 index 0000000..1ecb3ca --- /dev/null +++ b/fileio/fileglob.h @@ -0,0 +1,2 @@ +extern int bytes_read, bytes_written; + diff --git a/fileio/fileglob.o b/fileio/fileglob.o new file mode 100644 index 0000000..9d88693 Binary files /dev/null and b/fileio/fileglob.o differ diff --git a/fileio/kind.h b/fileio/kind.h new file mode 100755 index 0000000..d5400fb --- /dev/null +++ b/fileio/kind.h @@ -0,0 +1,10 @@ +#ifdef SCAN +#define UNIX_NAME 0 +#define PACK_NAME 1 +#define ARCH_NAME 2 +#define UNKNOWN 16 +#define PROTECTED 17 +#define ERROR 32 +#define COPY 33 +#endif /* SCAN */ + diff --git a/fileio/machdr.h b/fileio/machdr.h new file mode 100755 index 0000000..827aa1b --- /dev/null +++ b/fileio/machdr.h @@ -0,0 +1,20 @@ +#define INFOBYTES 128 + +/* The following are copied out of macput.c/macget.c */ +#define I_NAMEOFF 1 +/* 65 <-> 80 is the FInfo structure */ +#define I_TYPEOFF 65 +#define I_AUTHOFF 69 +#define I_FLAGOFF 73 +#define I_LOCKOFF 81 +#define I_DLENOFF 83 +#define I_RLENOFF 87 +#define I_CTIMOFF 91 +#define I_MTIMOFF 95 + +#define F_NAMELEN 63 +#define I_NAMELEN 69 /* 63 + strlen(".info") + 1 */ + +#define INITED_MASK 1 +#define PROTCT_MASK 0x40 + diff --git a/fileio/makefile b/fileio/makefile new file mode 100755 index 0000000..b46a7a3 --- /dev/null +++ b/fileio/makefile @@ -0,0 +1,33 @@ +CFLAGS= -O $(CF) + +all: wrfile.o rdfile.o fileglob.o + touch all + +wrfile.o: wrfile.c + +rdfile.o: rdfile.c + +clean: + -rm -f wrfile.o + -rm -f rdfile.o + -rm -f fileglob.o + -rm -f all + +wrfile.o: machdr.h +wrfile.o: wrfile.h +wrfile.o: wrfileopt.h +wrfile.o: fileglob.h +wrfile.o: aufs.h +wrfile.o: appledouble.h +wrfile.o: ../util/util.h +wrfile.o: ../util/curtime.h +rdfile.o: machdr.h +rdfile.o: rdfile.h +rdfile.o: rdfileopt.h +rdfile.o: ../util/util.h +rdfile.o: ../util/curtime.h +rdfile.o: ../util/masks.h +rdfile.o: aufs.h +rdfile.o: appledouble.h +fileglob.o: fileglob.h + diff --git a/fileio/rdfile.c b/fileio/rdfile.c new file mode 100755 index 0000000..f24e1cb --- /dev/null +++ b/fileio/rdfile.c @@ -0,0 +1,1010 @@ +#include +#ifdef TYPES_H +#include +#endif /* TYPES_H */ +#include +#include "machdr.h" +#include "rdfile.h" +#include "rdfileopt.h" +#ifndef DIRENT_H +#include +#define dirstruct direct +#else /* DIRENT_H */ +#include +#define dirstruct dirent +#endif /* DIRENT_H */ +#include "../util/curtime.h" +#include "../util/masks.h" +#include "../util/util.h" + +#ifdef AUFSPLUS +#define AUFS +#endif /* AUFSPLUS */ +#ifdef AUFS +#define APPLESHARE +#endif /* AUFS */ +#ifdef APPLEDOUBLE +#define APPLESHARE +#endif /* APPLEDOUBLE */ + +#define NOTFOUND 0 +#define ISFILE 1 +#define INFOFILE 2 +#define INFOEXT 3 +#define SKIPFILE 4 +#define MACBINARY 5 +#define DIRECTORY 6 +#ifdef APPLESHARE +#define SHAREFILE 7 +#endif /* APPLESHARE */ + +#define DATA_FORMAT 1 +#define RSRC_FORMAT 2 +#define UNIX_FORMAT 3 + +extern char *malloc(); +extern char *realloc(); +extern char *strcpy(); +extern char *strncpy(); +extern char *strcat(); +extern void exit(); + +static void check_files(); +static void read_file(); +static void enter_dir(); +static void exit_dir(); +static int get_stdin_file(); + +char file_info[INFOBYTES]; +char *data_fork, *rsrc_fork; +int data_size, rsrc_size; +static int max_data_size, max_rsrc_size; + +typedef struct filelist { + int nfiles; + char **files; + int *kind; + struct filelist *previous; + int current; +#ifdef APPLESHARE + int shared_dir; +#endif /* APPLESHARE */ +} filelist; + +static int data_only; +static int no_recurse; +static int read_stdin; +static filelist global_files; +static filelist *current_files; +static char f_auth[5]; +static char f_type[5]; +static char f_name[] = ".foldername"; +#ifdef APPLESHARE +#ifdef AUFS +#include "aufs.h" +static char infodir[] = ".finderinfo"; +static char rsrcdir[] = ".resource"; +static void read_aufs_info(); +#endif /* AUFS */ +#ifdef APPLEDOUBLE +#include "appledouble.h" +static char infodir[] = ".AppleDouble"; +static void read_appledouble_info(); +#endif /* APPLEDOUBLE */ +#endif /* APPLESHARE */ +static char filename[255]; +static int filekind; + +void setup(argc, argv) +int argc; +char **argv; +{ + if(argc == 0) { + read_stdin = 1; + } else { + read_stdin = 0; + global_files.previous = NULL; + global_files.nfiles = argc; + global_files.files = argv; + global_files.current = 0; + current_files = &global_files; + check_files(1); + } +} + +static void check_files(initial) +int initial; +{ + struct stat stbuf; + int i, j, n; + char filename[255], filename1[255]; + + /* Check the method to read the file */ + current_files->current = 0; + /* Set initially to NOTFOUND or DIRECTORY */ + n = current_files->nfiles; + current_files->kind = (int *)malloc((unsigned)n * sizeof(int)); + if(current_files->kind == NULL) { + (void)fprintf(stderr, "Insufficient memory\n"); + exit(1); + } + for(i = 0; i < n; i++) { + current_files->kind[i] = NOTFOUND; + if(stat(current_files->files[i], &stbuf) >= 0) { + if((stbuf.st_mode & S_IFMT) == S_IFDIR) { + /* We found a directory */ + current_files->kind[i] = DIRECTORY; + continue; + } + current_files->kind[i] = ISFILE; + } + } + /* That is enough for data_only mode */ + if(data_only) { + return; + } +#ifdef APPLESHARE + /* First check whether we are in a folder on a shared volume */ + i = 1; +#ifdef AUFS + if(stat(rsrcdir,&stbuf) < 0) { + i = 0; + } else { + if((stbuf.st_mode & S_IFMT) != S_IFDIR) { + i = 0; + } + } + if(stat(infodir,&stbuf) < 0) { + i = 0; + } else { + if((stbuf.st_mode & S_IFMT) != S_IFDIR) { + i = 0; + } + } +#endif /* AUFS */ +#ifdef APPLEDOUBLE + if(stat(infodir,&stbuf) < 0) { + i = 0; + } else { + if((stbuf.st_mode & S_IFMT) != S_IFDIR) { + i = 0; + } + } +#endif /* APPLEDOUBLE */ + current_files->shared_dir = i; +#endif /* APPLESHARE */ + for(i = 0; i < n; i++) { + if(current_files->kind[i] == NOTFOUND) { + j = 0; + } else if(current_files->kind[i] == ISFILE) { + /* Check whether the file is special */ +#ifdef APPLESHARE + if(!current_files->shared_dir && + !strcmp(current_files->files[i], f_name)) { + current_files->kind[i] = SKIPFILE; + continue; + } +#else /* APPLESHARE */ + if(!strcmp(current_files->files[i], f_name)) { + current_files->kind[i] = SKIPFILE; + continue; + } +#endif /* APPLESHARE */ + j = 1; + } else if(current_files->kind[i] == SKIPFILE) { + continue; + } else if(!initial) { /* DIRECTORY */ + /* Check whether the directory is special */ + if(!strcmp(current_files->files[i], ".") || + !strcmp(current_files->files[i], "..")) { + current_files->kind[i] = SKIPFILE; + } +#ifdef APPLESHARE +#ifdef AUFS + if(current_files->shared_dir && + (!strcmp(current_files->files[i], infodir) || + !strcmp(current_files->files[i], rsrcdir))) { + current_files->kind[i] = SKIPFILE; + } +#endif /* AUFS */ +#ifdef APPLEDOUBLE + if(current_files->shared_dir && + !strcmp(current_files->files[i], infodir)) { + current_files->kind[i] = SKIPFILE; + } +#endif /* APPLEDOUBLE */ +#endif /* APPLESHARE */ + continue; + } else { /* Take all directories from command line! */ + continue; + } +#ifdef APPLESHARE + /* Check whether file is in shared format */ + if(j & current_files->shared_dir) { + j = 0; + filename[0] = 0; + (void)strcat(filename, infodir); + (void)strcat(filename, "/"); + (void)strcat(filename, current_files->files[i]); + /* There ought to be an associated file in the info direcory */ + if(stat(filename, &stbuf) >= 0) { + current_files->kind[i] = SHAREFILE; + continue; + } + } +#endif /* APPLESHARE */ + /* If file not found check for the same with .info extension */ + if(!j) { + filename[0] = 0; + (void)strcat(filename, current_files->files[i]); + (void)strcat(filename, ".info"); + /* Found a .info file, else no such file found */ + if(stat(filename, &stbuf) >= 0) { + current_files->kind[i] = INFOEXT; + } + continue; + } + /* Now we found the file. Check first whether the name ends with + .info */ + j = strlen(current_files->files[i]) - 5; + if(!strncmp(current_files->files[i] + j, ".info", 5)) { + /* This is a .info file. Set as INFOFILE */ + current_files->kind[i] = INFOFILE; + /* Now remove from list of files the same with .data or .rsrc + extension */ + filename[0] = 0; + (void)strcat(filename, current_files->files[i]); + filename[j] = 0; + (void)strcpy(filename1, filename); + (void)strcat(filename, ".data"); + (void)strcat(filename1, ".rsrc"); + for(j = i + 1; j < n; j++) { + if(!strcmp(filename, current_files->files[j])) { + /* Associated .data file */ + current_files->kind[j] = SKIPFILE; + continue; + } + if(!strcmp(filename1, current_files->files[j])) { + /* Associated .rsrc file */ + current_files->kind[j] = SKIPFILE; + } + } + continue; + } + if(!strncmp(current_files->files[i] + j, ".data", 5) || + !strncmp(current_files->files[i] + j, ".rsrc", 5)) { + /* .data or .rsrc file found. Check whether there is an + associated .info file in the filelist */ + filename[0] = 0; + (void)strcat(filename, current_files->files[i]); + filename[j] = 0; + (void)strcat(filename, ".info"); + for(j = i + 1; j < n; j++) { + if(!strcmp(filename, current_files->files[j])) { + /* Found an associated .info file! */ + current_files->kind[i] = SKIPFILE; + break; + } + } + if(j < n) { + continue; + } + } + /* Finally nothing special */ + current_files->kind[i] = MACBINARY; + } +} + +int nextfile() +{ + int i; + + if(read_stdin) { + return get_stdin_file(); + } + i = current_files->current; +again: + if(i == current_files->nfiles) { + if(current_files->previous == NULL) { + return ISATEND; + } else { + exit_dir(); + current_files->current++; + return ENDDIR; + } + } + filename[0] = 0; + (void)strcat(filename, current_files->files[i]); + filekind = current_files->kind[i]; + switch(filekind) { + case DIRECTORY: + if(no_recurse) { + (void)fprintf(stderr, "Directory %s skipped.\n", filename); + i++; + current_files->current = i; + goto again; + } + enter_dir(); + return ISDIR; + case SKIPFILE: + i++; + current_files->current = i; + goto again; + case NOTFOUND: + (void)fprintf(stderr, "File %s not found.\n", filename); + exit(1); + default: + read_file(); + current_files->current = i + 1; + return ISFILE; + } +} + +static void read_file() +{ + FILE *fd; + int c, j, lname, skip; + struct stat stbuf; +#ifdef APPLESHARE + char filename1[255]; +#endif /* APPLESHARE */ + + switch(filekind) { + case ISFILE: + if(stat(filename, &stbuf) < 0) { + (void)fprintf(stderr, "Cannot stat file %s\n", filename); + exit(1); + } + for(j = 0; j < INFOBYTES; j++) { + file_info[j] = 0; + } + (void)strcpy(file_info + I_NAMEOFF + 1, filename); + file_info[I_NAMEOFF] = strlen(filename); + put4(file_info + I_CTIMOFF, (unsigned long)stbuf.st_ctime + TIMEDIFF); + put4(file_info + I_MTIMOFF, (unsigned long)stbuf.st_mtime + TIMEDIFF); + if(data_only == RSRC_FORMAT) { + rsrc_size = stbuf.st_size; + data_size = 0; + if(rsrc_size > max_rsrc_size) { + if(rsrc_fork == NULL) { + rsrc_fork = malloc((unsigned)rsrc_size); + } else { + rsrc_fork = realloc(rsrc_fork, (unsigned)rsrc_size); + } + max_rsrc_size = rsrc_size; + } + if(f_type[0] == 0) { + (void)strncpy(file_info + I_TYPEOFF, "RSRC", 4); + } else { + (void)strncpy(file_info + I_TYPEOFF, f_type, 4); + } + if(f_auth[0] == 0) { + (void)strncpy(file_info + I_AUTHOFF, "RSED", 4); + } else { + (void)strncpy(file_info + I_AUTHOFF, f_auth, 4); + } + put4(file_info + I_RLENOFF, (unsigned long)rsrc_size); + if((fd = fopen(filename, "r")) == NULL) { + (void)fprintf(stderr, "Cannot open file %s\n", filename); + exit(1); + } + if(fread(rsrc_fork, 1, rsrc_size, fd) != rsrc_size) { + (void)fprintf(stderr, "Short file %s\n", filename); + exit(1); + } + (void)fclose(fd); + } else { + data_size = stbuf.st_size; + rsrc_size = 0; + if(data_size > max_data_size) { + if(data_fork == NULL) { + data_fork = malloc((unsigned)data_size); + } else { + data_fork = realloc(data_fork, (unsigned)data_size); + } + max_data_size = data_size; + } + if(f_type[0] == 0) { + (void)strncpy(file_info + I_TYPEOFF, "TEXT", 4); + } else { + (void)strncpy(file_info + I_TYPEOFF, f_type, 4); + } + if(f_auth[0] == 0) { + (void)strncpy(file_info + I_AUTHOFF, "MACA", 4); + } else { + (void)strncpy(file_info + I_AUTHOFF, f_auth, 4); + } + put4(file_info + I_DLENOFF, (unsigned long)data_size); + if((fd = fopen(filename, "r")) == NULL) { + (void)fprintf(stderr, "Cannot open file %s\n", filename); + exit(1); + } + if(fread(data_fork, 1, data_size, fd) != data_size) { + (void)fprintf(stderr, "Short file %s\n", filename); + exit(1); + } + (void)fclose(fd); + if(data_only == UNIX_FORMAT) { + for(j = 0; j < data_size; j++) { + c = data_fork[j]; + if(c == '\012' || c == '\015') { + data_fork[j] = '\027' -c; + } + } + } + } + break; + case INFOEXT: + (void)strcat(filename, ".info"); + case INFOFILE: + lname = strlen(filename) - 5; + if((fd = fopen(filename, "r")) == NULL) { + (void)fprintf(stderr, "Cannot open file %s\n", filename); + exit(1); + } + if(fread(file_info, 1, INFOBYTES, fd) != INFOBYTES) { + (void)fprintf(stderr, "Cannot read info header %s\n", filename); + } + (void)fclose(fd); + data_size = get4(file_info + I_DLENOFF); + rsrc_size = get4(file_info + I_RLENOFF); + if(data_size > max_data_size) { + if(data_fork == NULL) { + data_fork = malloc((unsigned)data_size); + } else { + data_fork = realloc(data_fork, (unsigned)data_size); + } + max_data_size = data_size; + } + if(rsrc_size > max_rsrc_size) { + if(rsrc_fork == NULL) { + rsrc_fork = malloc((unsigned)rsrc_size); + } else { + rsrc_fork = realloc(rsrc_fork, (unsigned)rsrc_size); + } + max_rsrc_size = rsrc_size; + } + if(data_size != 0) { + filename[lname] = 0; + (void)strcat(filename, ".data"); + if((fd = fopen(filename, "r")) == NULL) { + (void)fprintf(stderr, "Cannot open data fork %s\n", filename); + exit(1); + } + if(fread(data_fork, 1, data_size, fd) != data_size) { + (void)fprintf(stderr, "Premature EOF on %s\n", filename); + } + (void)fclose(fd); + } + if(rsrc_size != 0) { + filename[lname] = 0; + (void)strcat(filename, ".rsrc"); + if((fd = fopen(filename, "r")) == NULL) { + (void)fprintf(stderr, "Cannot open rsrc fork %s\n", filename); + exit(1); + } + if(fread(rsrc_fork, 1, rsrc_size, fd) != rsrc_size) { + (void)fprintf(stderr, "Premature EOF on %s\n", filename); + } + (void)fclose(fd); + } + break; + case MACBINARY: + if((fd = fopen(filename, "r")) == NULL) { + (void)fprintf(stderr, "Cannot open file %s\n", filename); + exit(1); + } + if(fread(file_info, 1, INFOBYTES, fd) != INFOBYTES) { + (void)fprintf(stderr, "Short file %s\n", filename); + exit(1); + } + if(file_info[0] != 0) { + (void)fprintf(stderr, "File is not MacBinary: %s\n", filename); + exit(1); + } + data_size = get4(file_info + I_DLENOFF); + rsrc_size = get4(file_info + I_RLENOFF); + if(file_info[I_LOCKOFF] & 1) { + file_info[I_FLAGOFF + 1] = PROTCT_MASK; + file_info[I_LOCKOFF] &= ~1; + } + if(data_size != 0) { + if(data_size > max_data_size) { + if(data_fork == NULL) { + data_fork = malloc((unsigned)data_size); + } else { + data_fork = realloc(data_fork, (unsigned)data_size); + } + max_data_size = data_size; + } + if(fread(data_fork, 1, data_size, fd) != data_size) { + (void)fprintf(stderr, "Short file %s\n", filename); + exit(1); + } + skip = (((data_size + 127) >> 7) << 7) - data_size; + for(j = 0; j < skip; j++) { + (void)fgetc(fd); + } + } + if(rsrc_size != 0) { + if(rsrc_size > max_rsrc_size) { + if(rsrc_fork == NULL) { + rsrc_fork = malloc((unsigned)rsrc_size); + } else { + rsrc_fork = realloc(rsrc_fork, (unsigned)rsrc_size); + } + max_rsrc_size = rsrc_size; + } + if(fread(rsrc_fork, 1, rsrc_size, fd) != rsrc_size) { + (void)fprintf(stderr, "Short file %s\n", filename); + exit(1); + } + } + break; +#ifdef APPLESHARE + case SHAREFILE: +#ifdef AUFS + (void)strcpy(filename1, infodir); + (void)strcat(filename1, "/"); + (void)strcat(filename1, filename); + if((fd = fopen(filename1, "r")) == NULL) { + (void)fprintf(stderr, "Cannot open file %s\n", filename1); + } + read_aufs_info(fd); + (void)fclose(fd); + (void)strcpy(filename1, rsrcdir); + (void)strcat(filename1, "/"); + (void)strcat(filename1, filename); + if(stat(filename1, &stbuf) >= 0) { + rsrc_size = stbuf.st_size; + put4(file_info + I_RLENOFF, (unsigned long)rsrc_size); + if(rsrc_size > 0) { + if(rsrc_size > max_rsrc_size) { + if(rsrc_fork == NULL) { + rsrc_fork = malloc((unsigned)rsrc_size); + } else { + rsrc_fork = realloc(rsrc_fork, (unsigned)rsrc_size); + } + max_rsrc_size = rsrc_size; + } + if((fd = fopen(filename1, "r")) == NULL) { + (void)fprintf(stderr, "Cannot open file %s\n", filename1); + exit(1); + } + if(fread(rsrc_fork, 1, rsrc_size, fd) != rsrc_size) { + (void)fprintf(stderr, "Short file %s\n", filename1); + exit(1); + } + (void)fclose(fd); + } + } + if(stat(filename, &stbuf) >= 0) { + data_size = stbuf.st_size; + put4(file_info + I_DLENOFF, (unsigned long)data_size); + if(data_size > 0) { + if(data_size > max_data_size) { + if(data_fork == NULL) { + data_fork = malloc((unsigned)data_size); + } else { + data_fork = realloc(data_fork, (unsigned)data_size); + } + max_data_size = data_size; + } + if((fd = fopen(filename, "r")) == NULL) { + (void)fprintf(stderr, "Cannot open file %s\n", filename); + exit(1); + } + if(fread(data_fork, 1, data_size, fd) != data_size) { + (void)fprintf(stderr, "Short file %s\n", filename1); + exit(1); + } + (void)fclose(fd); + } + } +#endif /* AUFS */ +#ifdef APPLEDOUBLE + (void)strcpy(filename1, infodir); + (void)strcat(filename1, "/"); + (void)strcat(filename1, filename); + if((fd = fopen(filename1, "r")) == NULL) { + (void)fprintf(stderr, "Cannot open file %s\n", filename1); + } + read_appledouble_info(fd); + rsrc_size = get4(file_info + I_RLENOFF); + if(rsrc_size > 0) { + if(rsrc_size > max_rsrc_size) { + if(rsrc_fork == NULL) { + rsrc_fork = malloc((unsigned)rsrc_size); + } else { + rsrc_fork = realloc(rsrc_fork, (unsigned)rsrc_size); + } + max_rsrc_size = rsrc_size; + } + if(fread(rsrc_fork, 1, rsrc_size, fd) != rsrc_size) { + (void)fprintf(stderr, "Short file %s\n", filename1); + exit(1); + } + } + (void)fclose(fd); + if(stat(filename, &stbuf) >= 0) { + data_size = stbuf.st_size; + put4(file_info + I_DLENOFF, (unsigned long)data_size); + if(data_size > 0) { + if(data_size > max_data_size) { + if(data_fork == NULL) { + data_fork = malloc((unsigned)data_size); + } else { + data_fork = realloc(data_fork, (unsigned)data_size); + } + max_data_size = data_size; + } + if((fd = fopen(filename, "r")) == NULL) { + (void)fprintf(stderr, "Cannot open file %s\n", filename); + exit(1); + } + if(fread(data_fork, 1, data_size, fd) != data_size) { + (void)fprintf(stderr, "Short file %s\n", filename1); + exit(1); + } + (void)fclose(fd); + } + } +#endif /* APPLEDOUBLE */ + break; +#endif /* APPLESHARE */ + } +} + +static void enter_dir() +{ + DIR *directory; + struct dirstruct *curentry; + FILE *fd; + int n, j, namlen; + int listsize, cursize; + char *filetable; + filelist *new_files; +#ifdef APPLESHARE + char filename1[255]; +#endif /* APPLESHARE */ + + for(j = 0; j < INFOBYTES; j++) { + file_info[j] = 0; + } + (void)strcpy(file_info + I_NAMEOFF + 1, filename); + file_info[I_NAMEOFF] = strlen(filename); + directory = opendir(filename); + if(directory == NULL) { + (void)fprintf(stderr, "Cannot read directory %s\n", filename); + exit(1); + } + listsize = 1024; + filetable = malloc((unsigned)listsize); + cursize = 0; + n = 0; + while((curentry = readdir(directory)) != NULL) { + namlen = strlen(curentry->d_name); + if(namlen + 1 > listsize - cursize) { + listsize += 1024; + filetable = realloc(filetable, (unsigned)listsize); + } + (void)strcpy(filetable + cursize, curentry->d_name); + cursize += (namlen + 1); + n++; + } + filetable = realloc(filetable, (unsigned)cursize); + (void)closedir(directory); + new_files = (filelist *)malloc(sizeof(filelist)); + new_files->nfiles = n; + new_files->files = (char **)malloc((unsigned)n * sizeof(char **)); + new_files->kind = (int *)malloc((unsigned)n * sizeof(int)); + new_files->previous = current_files; + new_files->current = 0; + cursize = 0; + for(j = 0; j < n; j++) { + new_files->files[j] = filetable + cursize; + cursize += (strlen(filetable + cursize) + 1); + } + (void)chdir(filename); +#ifdef APPLESHARE + if((fd = fopen(f_name, "r")) != NULL) { + if(fread(file_info, 1, INFOBYTES, fd) != INFOBYTES) { + (void)fprintf(stderr, "File error on %s\n", f_name); + exit(1); + } + file_info[I_NAMEOFF] |= 0x80; + (void)fclose(fd); + } else { +#ifdef AUFS + (void)strcpy(filename1, "../"); + (void)strcat(filename1, infodir); + (void)strcat(filename1, "/"); + (void)strcat(filename1, filename); + if((fd = fopen(filename1, "r")) != NULL) { + read_aufs_info(fd); + (void)fclose(fd); + } +#endif /* AUFS */ +#ifdef APPLEDOUBLE + (void)strcpy(filename1, infodir); + (void)strcat(filename1, "/.Parent"); + if((fd = fopen(filename1, "r")) != NULL) { + read_appledouble_info(fd); + (void)fclose(fd); + } +#endif /* APPLEDOUBLE */ + file_info[I_NAMEOFF] |= 0x80; + } +#else /* APPLESHARE */ + if((fd = fopen(f_name, "r")) != NULL) { + if(fread(file_info, 1, INFOBYTES, fd) != INFOBYTES) { + (void)fprintf(stderr, "File error on %s\n", f_name); + exit(1); + } + file_info[I_NAMEOFF] |= 0x80; + (void)fclose(fd); + } +#endif /* APPLESHARE */ + current_files = new_files; + check_files(0); +} + +static void exit_dir() +{ + filelist *old_files; + int i; + + for(i = 0; i < INFOBYTES; i++) { + file_info[i] = 0; + } + file_info[I_NAMEOFF] = 0x80; + old_files = current_files; + /* Do some garbage collection here! */ + current_files = current_files->previous; + (void)free(old_files->files[0]); + (void)free((char *)old_files->files); + (void)free((char *)old_files->kind); + (void)free((char *)old_files); + (void)chdir(".."); +} + +#ifdef APPLESHARE +#ifdef AUFS +static void read_aufs_info(fd) +FILE *fd; +{ + FileInfo theinfo; + int i, n; + struct stat stbuf; + + for(i = 0; i < INFOBYTES; i++) { + file_info[i] = 0; + } + bzero((char *) &theinfo, sizeof(theinfo)); + if(fread((char *)&theinfo, 1, sizeof(theinfo), fd) != sizeof(theinfo)) { + (void)fprintf(stderr, "Short AUFS info header for %s\n", filename); + exit(1); + } + if(theinfo.fi_magic1 & BYTEMASK != FI_MAGIC1 || + theinfo.fi_version & BYTEMASK != FI_VERSION || + theinfo.fi_magic & BYTEMASK != FI_MAGIC) { + (void)fprintf(stderr, "Magic number mismatch on %s\n", filename); + exit(1); + } + bcopy(theinfo.fi_fndr, file_info + I_TYPEOFF, 4); + bcopy(theinfo.fi_fndr + 4, file_info + I_AUTHOFF, 4); + bcopy(theinfo.fi_fndr + 8, file_info + I_FLAGOFF, 2); + if(theinfo.fi_bitmap & FI_BM_MACINTOSHFILENAME) { + n = strlen(theinfo.fi_macfilename); + (void)strncpy(file_info + I_NAMEOFF + 1, (char *)theinfo.fi_macfilename, + n); + } else if(theinfo.fi_bitmap & FI_BM_SHORTFILENAME) { + n = strlen(theinfo.fi_shortfilename); + (void)strncpy(file_info + I_NAMEOFF + 1, + (char *)theinfo.fi_shortfilename, n); + } else { + n = strlen(filename); + (void)strncpy(file_info + I_NAMEOFF + 1, filename, n); + } + file_info[I_NAMEOFF] = n; +#ifdef AUFSPLUS + if(theinfo.fi_datemagic == FI_MAGIC && + (theinfo.fi_datevalid & (FI_CDATE | FI_MDATE)) == + (FI_CDATE | FI_MDATE)) { + put4(file_info + I_CTIMOFF, get4(theinfo.fi_ctime) + TIMEDIFF); + put4(file_info + I_MTIMOFF, get4(theinfo.fi_mtime) + TIMEDIFF); + } else { + if(fstat(fileno(fd), &stbuf) >= 0) { + put4(file_info + I_CTIMOFF, + (unsigned long)stbuf.st_ctime + TIMEDIFF); + put4(file_info + I_MTIMOFF, + (unsigned long)stbuf.st_mtime + TIMEDIFF); + } + } +#else /* AUFSPLUS */ + if(fstat(fileno(fd), &stbuf) >= 0) { + put4(file_info + I_CTIMOFF, (unsigned long)stbuf.st_ctime + TIMEDIFF); + put4(file_info + I_MTIMOFF, (unsigned long)stbuf.st_mtime + TIMEDIFF); + } +#endif /* AUFSPLUS */ +} +#endif /* AUFS */ + +#ifdef APPLEDOUBLE +/* This version assumes that the AppleDouble info header is always the same + size and format. I have not yet seen something that will lead me to + believe different. +*/ +static void read_appledouble_info(fd) +FILE *fd; +{ + FileInfo theinfo; + int i, n; + + for(i = 0; i < INFOBYTES; i++) { + file_info[i] = 0; + } + bzero((char *) &theinfo, sizeof(theinfo)); + if(fread((char *)&theinfo, 1, sizeof(theinfo), fd) != sizeof(theinfo)) { + (void)fprintf(stderr, "Short AppleDouble info header for %s\n", + filename); + exit(1); + } + if(get4(theinfo.fi_magic) != FI_MAGIC || + get2(theinfo.fi_version) != FI_VERSION) { + (void)fprintf(stderr, "Magic number mismatch on %s\n", filename); + exit(1); + } + bcopy(theinfo.fi_type, file_info + I_TYPEOFF, 4); + bcopy(theinfo.fi_auth, file_info + I_AUTHOFF, 4); + bcopy(theinfo.fi_finfo, file_info + I_FLAGOFF, 2); + n = get4(theinfo.fi_namlen); + (void)strncpy(file_info + I_NAMEOFF + 1, theinfo.fi_name, n); + file_info[I_NAMEOFF] = n; + put4(file_info + I_CTIMOFF, get4(theinfo.fi_ctime) + TIMEDIFF); + put4(file_info + I_MTIMOFF, get4(theinfo.fi_mtime) + TIMEDIFF); + rsrc_size = get4(theinfo.fi_rsrc); + put4(file_info + I_RLENOFF, (unsigned long)rsrc_size); +} +#endif /* APPLEDOUBLE */ +#endif /* APPLESHARE */ + +static int get_stdin_file() +{ + int i, skip; + + i = fgetc(stdin); + if(i == EOF) { + return ISATEND; + } + (void)ungetc(i, stdin); + if(fread(file_info, 1, INFOBYTES, stdin) != INFOBYTES) { + (void)fprintf(stderr, "Short input\n"); + exit(1); + } + if(file_info[0] != 0) { + (void)fprintf(stderr, "File is not MacBinary: %s\n", filename); + exit(1); + } + data_size = get4(file_info + I_DLENOFF); + rsrc_size = get4(file_info + I_RLENOFF); + if(file_info[I_LOCKOFF] & 1) { + file_info[I_FLAGOFF + 1] = PROTCT_MASK; + file_info[I_LOCKOFF] &= ~1; + } + if(data_size != 0) { + if(data_size > max_data_size) { + if(data_fork == NULL) { + data_fork = malloc((unsigned)data_size); + } else { + data_fork = realloc(data_fork, (unsigned)data_size); + } + max_data_size = data_size; + } + if(fread(data_fork, 1, data_size, stdin) != data_size) { + (void)fprintf(stderr, "Short input\n"); + exit(1); + } + skip = (((data_size + 127) >> 7) << 7) - data_size; + for(i = 0; i < skip; i++) { + (void)fgetc(stdin); + } + } + if(rsrc_size != 0) { + if(rsrc_size > max_rsrc_size) { + if(rsrc_fork == NULL) { + rsrc_fork = malloc((unsigned)rsrc_size); + } else { + rsrc_fork = realloc(rsrc_fork, (unsigned)rsrc_size); + } + max_rsrc_size = rsrc_size; + } + if(fread(rsrc_fork, 1, rsrc_size, stdin) != rsrc_size) { + (void)fprintf(stderr, "Short input\n"); + exit(1); + } + skip = (((rsrc_size + 127) >> 7) << 7) - rsrc_size; + for(i = 0; i < skip; i++) { + (void)fgetc(stdin); + } + } + if(file_info[I_NAMEOFF] & 0x80) { + if((file_info[I_NAMEOFF] & 0xff) == 0x80) { + return ENDDIR; + } + return ISDIR; + } + return ISFILE; +} + +int rdfileopt(c) +char c; +{ +extern char *optarg; +char name[32]; + + switch(c) { + case 'd': + data_only = DATA_FORMAT; + break; + case 'u': + case 'U': + data_only = UNIX_FORMAT; + break; + case 'r': + data_only = RSRC_FORMAT; + break; + case 'c': + backtrans(name, optarg); + (void)strncpy(f_auth, name, 4); + break; + case 't': + backtrans(name, optarg); + (void)strncpy(f_type, name, 4); + break; + default: + return 0; + } + return 1; +} + +void give_rdfileopt() +{ + (void)fprintf(stderr, "File input options:\n"); + (void)fprintf(stderr, "-r:\tread as resource files\n"); + (void)fprintf(stderr, "-d:\tread as data files\n"); + (void)fprintf(stderr, + "-u:\tread as data files with Unix -> Mac text file translation\n"); + (void)fprintf(stderr, "-U:\ta synonym for -u\n"); + (void)fprintf(stderr, + "-c cr:\tcreator if one of the above options is used\n"); + (void)fprintf(stderr, + "-t ty:\tfiletype if one of the above options is used\n"); +} + +void set_norecurse() +{ + no_recurse = 1; +} + +char *get_rdfileopt() +{ + static char options[] = "rduUc:t:"; + + return options; +} + +char *get_minb() +{ +#ifdef APPLESHARE +#ifdef AUFS + return ", AUFS supported"; +#endif /* AUFS */ +#ifdef APPLEDOUBLE + return ", AppleDouble supported"; +#endif /* APPLEDOUBLE */ +#else /* APPLESHARE */ + return ", no Apple-Unix sharing supported"; +#endif /* APPLESHARE */ +} + diff --git a/fileio/rdfile.h b/fileio/rdfile.h new file mode 100755 index 0000000..05e65a4 --- /dev/null +++ b/fileio/rdfile.h @@ -0,0 +1,13 @@ +#define ISATEND 0 +#define ISFILE 1 +#define ISDIR 2 +#define ENDDIR 3 + +extern char file_info[INFOBYTES]; +extern char *data_fork, *rsrc_fork; +extern int data_size, rsrc_size; + +extern void setup(); +extern int nextfile(); +extern char *get_minb(); + diff --git a/fileio/rdfile.o b/fileio/rdfile.o new file mode 100644 index 0000000..8b09567 Binary files /dev/null and b/fileio/rdfile.o differ diff --git a/fileio/rdfileopt.h b/fileio/rdfileopt.h new file mode 100755 index 0000000..74cafa1 --- /dev/null +++ b/fileio/rdfileopt.h @@ -0,0 +1,5 @@ +extern int rdfileopt(); +extern void give_rdfileopt(); +extern void set_norecurse(); +extern char *get_rdfileopt(); + diff --git a/fileio/wrfile.c b/fileio/wrfile.c new file mode 100755 index 0000000..59a2c65 --- /dev/null +++ b/fileio/wrfile.c @@ -0,0 +1,847 @@ +#ifdef TYPES_H +#include +#endif /* TYPES_H */ +#include +#include +#include +#include "machdr.h" +#include "wrfile.h" +#include "wrfileopt.h" +#include "../util/util.h" +#ifdef AUFSPLUS +#include "../util/curtime.h" +#define AUFS +#endif /* AUFSPLUS */ +#ifdef AUFS +#include "aufs.h" +#define APPLESHARE +#endif /* AUFS */ +#ifdef APPLEDOUBLE +#include "appledouble.h" +#include "../util/curtime.h" +#define APPLESHARE +#endif /* APPLEDOUBLE */ + +#define TEXT 0 +#define DATA 1 +#define RSRC 2 +#define FULL 3 +#define MACB 4 +#define FORK 5 +#define APSH 6 +#define MACS 7 +#define UNIX 8 +#ifdef SCAN +#define MACI 9 +#endif /* SCAN */ + +extern char *malloc(); +extern char *realloc(); +extern char *strcpy(); +extern char *strncpy(); +extern char *strcat(); +extern void exit(); + +#ifdef UNDEF /* Do not declare sprintf; not portable (but lint will complain) */ +char *sprintf(); +#endif /* UNDEF */ + +#ifdef AUFS +static void check_aufs(); +static void aufs_namings(); +static void wr_aufs_info(); +#endif /* AUFS */ +#ifdef APPLEDOUBLE +static void check_appledouble(); +static void appledouble_namings(); +static void wr_appledouble_info(); +#endif /* APPLEDOUBLE */ +#ifdef APPLESHARE +static void mk_share_name(); +#endif /* APPLESHARE */ + +#ifndef BSD +/* all those stupid differences! */ +#define bcopy(src,dest,length) memcpy((dest),(src),(length)) +#define bzero(block,length) memset((block),0,(length)) +#endif /* BSD */ + +#define INFO_FORK 1 +#define RSRC_FORK 2 +#define DATA_FORK 3 + +static char f_info[I_NAMELEN]; +static char f_data[I_NAMELEN*3]; +static char f_rsrc[I_NAMELEN]; +static char f_text[I_NAMELEN]; +static char f_unix[I_NAMELEN]; +static char f_bin[I_NAMELEN]; +static char f_folder[] = ".foldername"; +static char share_name[256]; +#ifdef APPLESHARE +static char hex[] = "0123456789abcdef"; +#endif /* APPLESHARE */ +#ifdef AUFS +static char infodir[] = ".finderinfo"; +static char rsrcdir[] = ".resource"; +#define INFOSZ sizeof(infodir) +#define RSRCSZ sizeof(rsrcdir) +static char f_info_aufs[I_NAMELEN*3+INFOSZ]; +static char f_rsrc_aufs[I_NAMELEN*3+RSRCSZ]; +#endif /* AUFS */ +#ifdef APPLEDOUBLE +static char infodir[] = ".AppleDouble"; +#define INFOSZ sizeof(infodir) +static char f_info_appledouble[I_NAMELEN*3+INFOSZ]; +#endif /* APPLEDOUBLE */ + +static int mode = MACB; +static int mode_restricted = 0; +static int mode_s_restricted = 0; +char *out_buffer, *out_ptr; + +static char init_buffer[128]; +static char *buffer = &(init_buffer[0]); +static char *rbuffer = NULL, *dbuffer = NULL; +static char *ptr; +static unsigned long rsz, dsz, totsize, maxsize; + +void define_name(text) +char *text; +{ + (void)sprintf(f_info, "%s.info", text); + (void)sprintf(f_rsrc, "%s.rsrc", text); + (void)sprintf(f_data, "%s.data", text); + (void)sprintf(f_text, "%s.text", text); + (void)sprintf(f_bin, "%s.bin", text); + (void)sprintf(f_unix, "%s", text); +#ifdef APPLESHARE +/* Do not do namestuffing here. We want to base again on the information in + the info header, so this is delayed +*/ +#endif /* APPLESHARE */ +} + +void start_info(info, rsize, dsize) +char *info; +unsigned long rsize, dsize; +{ + int rs, ds; + + rsz = rsize; + dsz = dsize; + rs = (((rsz + 127) >> 7) << 7); + ds = (((dsz + 127) >> 7) << 7); + totsize = rs + ds + 128; + if(buffer == &(init_buffer[0])) { + buffer = (char *)malloc((unsigned)totsize); + } else if(maxsize < totsize) { + buffer = (char *)realloc(buffer, (unsigned)totsize); + } + maxsize = totsize; + if(buffer == NULL) { + (void)fprintf(stderr, "Insufficient memory, aborting\n"); + exit(1); + } + dbuffer = buffer + 128; + rbuffer = dbuffer + ds; + (void)bzero(buffer, (int)totsize); + ptr = buffer; + (void)bcopy(info, ptr, 128); +#ifdef AUFS +/* Now we do filenaming etc. */ + if(mode == APSH) { + aufs_namings(); + } +#endif /* AUFS */ +#ifdef APPLEDOUBLE +/* Now we do filenaming etc. */ + if(mode == APSH) { + appledouble_namings(); + } +#endif /* APPLEDOUBLE */ +} + +void start_rsrc() +{ + out_buffer = out_ptr = rbuffer; +} + +void start_data() +{ + out_buffer = out_ptr = dbuffer; +} + +void end_file() +{ + FILE *fp; + int i, c; + + buffer[I_FLAGOFF] &= (~INITED_MASK); + switch(mode) { + case FULL: + case FORK: + fp = fopen(f_info, "w"); + if(fp == NULL) { + perror(f_info); + exit(1); + } + (void)fwrite(buffer, 1, 128, fp); + (void)fclose(fp); + if(rsz != 0 || mode == FULL) { + fp = fopen(f_rsrc, "w"); + if(fp == NULL) { + perror(f_rsrc); + exit(1); + } + (void)fwrite(rbuffer, 1, (int)rsz, fp); + (void)fclose(fp); + } + if(dsz != 0 || mode == FULL) { + fp = fopen(f_data, "w"); + if(fp == NULL) { + perror(f_data); + exit(1); + } + (void)fwrite(dbuffer, 1, (int)dsz, fp); + (void)fclose(fp); + } + break; + case RSRC: + fp = fopen(f_rsrc, "w"); + if(fp == NULL) { + perror(f_rsrc); + exit(1); + } + (void)fwrite(rbuffer, 1, (int)rsz, fp); + (void)fclose(fp); + break; + case DATA: + fp = fopen(f_data, "w"); + if(fp == NULL) { + perror(f_data); + exit(1); + } + (void)fwrite(dbuffer, 1, (int)dsz, fp); + (void)fclose(fp); + break; + case TEXT: + fp = fopen(f_text, "w"); + if(fp == NULL) { + perror(f_data); + exit(1); + } + for(i = 0; i < dsz; i++) { + c = dbuffer[i]; + if(c == '\012' || c == '\015') { + dbuffer[i] = '\027' -c; + } + } + (void)fwrite(dbuffer, 1, (int)dsz, fp); + (void)fclose(fp); + break; + case UNIX: + fp = fopen(f_unix, "w"); + if(fp == NULL) { + perror(f_data); + exit(1); + } + for(i = 0; i < dsz; i++) { + c = dbuffer[i]; + if(c == '\012' || c == '\015') { + dbuffer[i] = '\027' -c; + } + } + (void)fwrite(dbuffer, 1, (int)dsz, fp); + (void)fclose(fp); + break; + case MACB: + fp = fopen(f_bin, "w"); + if(fp == NULL) { + perror(f_bin); + exit(1); + } + if(buffer[I_FLAGOFF + 1] & PROTCT_MASK) { + buffer[I_LOCKOFF] = 1; + } + buffer[I_FLAGOFF + 1] = 0; + buffer[I_LOCKOFF + 1] = 0; + (void)fwrite(buffer, 1, (int)totsize, fp); + (void)fclose(fp); + break; + case MACS: +#ifdef SCAN + case MACI: +#endif /* SCAN */ + if(buffer[I_FLAGOFF + 1] & PROTCT_MASK) { + buffer[I_LOCKOFF] = 1; + } + buffer[I_FLAGOFF + 1] = 0; + buffer[I_LOCKOFF + 1] = 0; + (void)fwrite(buffer, 1, (int)totsize, stdout); + break; +#ifdef AUFS + case APSH: + fp = fopen(f_info_aufs, "w"); + if(fp == NULL) { + perror(f_info_aufs); + exit(1); + } + wr_aufs_info(fp); + (void) fclose(fp); + fp = fopen(f_rsrc_aufs, "w"); + if(fp == NULL) { + perror(f_rsrc_aufs); + exit(1); + } + (void)fwrite(rbuffer, 1, (int)rsz, fp); + (void)fclose(fp); + fp = fopen(f_data, "w"); + if(fp == NULL) { + perror(f_data); + exit(1); + } + (void)fwrite(dbuffer, 1, (int)dsz, fp); + (void)fclose(fp); + break; +#endif /* AUFS */ +#ifdef APPLEDOUBLE + case APSH: + fp = fopen(f_info_appledouble, "w"); + if(fp == NULL) { + perror(f_info_appledouble); + exit(1); + } + wr_appledouble_info(fp); + (void)fwrite(rbuffer, 1, (int)rsz, fp); + (void)fclose(fp); + fp = fopen(f_data, "w"); + if(fp == NULL) { + perror(f_data); + exit(1); + } + (void)fwrite(dbuffer, 1, (int)dsz, fp); + (void)fclose(fp); + break; +#endif /* APPLEDOUBLE */ + } +} + +#ifdef SCAN +void do_idf(name, kind) +char *name; +int kind; +{ + int n; + + if(mode != MACI) { + return; + } + n = strlen(name); + (void)bzero(buffer, INFOBYTES); + buffer[I_NAMEOFF + 1] = kind; + put4(buffer + I_DLENOFF, (unsigned long)n); + (void)fwrite(buffer, 1, INFOBYTES, stdout); + if(n != 0) { + (void)fwrite(name, 1, n, stdout); + n = (((n + 127) >> 7) << 7) - n; + while(n-- > 0) { + (void)fputc(0, stdout); + } + } +} +#endif /* SCAN */ + +void do_mkdir(name, header) +char *name, *header; +{ +struct stat sbuf; +FILE *fp; +#ifdef NOMKDIR +char command[21]; /* Systems without mkdir system call but more than 14 + char file names? Ridiculous! */ +int sysreturn; +#endif /* MKDIR */ +#ifdef APPLESHARE +char dirinfo[I_NAMELEN*3+INFOSZ+10]; +#endif /* APPLESHARE */ + +#ifndef SCAN + if(mode == MACS) { +#else /* SCAN */ + if(mode == MACS || mode == MACI) { +#endif /* SCAN */ + header[I_NAMEOFF] |= 0x80; + (void)fwrite(header, 1, INFOBYTES, stdout); + header[I_NAMEOFF] &= 0x7f; + return; + } +#ifdef APPLESHARE + if(mode == APSH) { + (void)bcopy(header, buffer, INFOBYTES); + mk_share_name(); + } else { + (void)strcpy(share_name, name); + } +#else /* APPLESHARE */ + (void)strcpy(share_name, name); +#endif /* APPLESHARE */ + if(stat(share_name, &sbuf) == -1) { /* directory doesn't exist */ +#ifndef NOMKDIR + if(mkdir(share_name, 0777) == -1) { + (void)fprintf(stderr, "Can't create subdirectory %s\n", share_name); + exit(1); + } +#else /* NOMKDIR */ + sprintf(command, "mkdir %s", share_name); + if((sysreturn = system(command)) != 0) { + (void)fprintf(stderr, "Can't create subdirectory %s\n", share_name); + exit(sysreturn); + } +#endif /* NOMKDIR */ + } else { /* something exists with this name */ + if((sbuf.st_mode & S_IFMT) != S_IFDIR) { + (void)fprintf(stderr, "Directory name %s already in use\n", + share_name); + exit(1); + } + } + (void)chdir(share_name); +#ifdef APPLESHARE +#ifdef AUFS + if(mode == APSH) { + if(stat(rsrcdir, &sbuf) == -1) { /* directory doesn't exist */ + if(mkdir(rsrcdir, 0777) == -1) { + (void)fprintf(stderr, "Can't create subdirectory %s\n", + rsrcdir); + exit(1); + } + } else { + if((sbuf.st_mode & S_IFMT) != S_IFDIR) { + (void)fprintf(stderr, "Directory name %s already in use\n", + rsrcdir); + exit(1); + } + } + if(stat(infodir, &sbuf) == -1) { /* directory doesn't exist */ + if(mkdir(infodir, 0777) == -1) { + (void)fprintf(stderr, "Can't create subdirectory %s\n", + infodir); + exit(1); + } + } else { + if((sbuf.st_mode & S_IFMT) != S_IFDIR) { + (void)fprintf(stderr, "Directory name %s already in use\n", + infodir); + exit(1); + } + } + dirinfo[0] = 0; + (void)strcat(dirinfo, "../"); + (void)strcat(dirinfo, infodir); + (void)strcat(dirinfo, "/"); + (void)strcat(dirinfo, share_name); + fp = fopen(dirinfo, "w"); + if(fp == NULL) { + perror(dirinfo); + exit(1); + } + wr_aufs_info(fp); + (void)fclose(fp); + } else { + fp = fopen(f_folder, "w"); + if(fp == NULL) { + perror(f_folder); + exit(1); + } + header[I_NAMEOFF] |= 0x80; + (void)fwrite(header, 1, INFOBYTES, fp); + header[I_NAMEOFF] &= 0x7f; + (void)fclose(fp); + } +#endif /* AUFS */ +#ifdef APPLEDOUBLE + if(mode == APSH) { + if(stat(infodir, &sbuf) == -1) { /* directory doesn't exist */ + if(mkdir(infodir, 0777) == -1) { + (void)fprintf(stderr, "Can't create subdirectory %s\n", + infodir); + exit(1); + } + } else { + if((sbuf.st_mode & S_IFMT) != S_IFDIR) { + (void)fprintf(stderr, "Directory name %s already in use\n", + infodir); + exit(1); + } + } + dirinfo[0] = 0; + (void)strcat(dirinfo, infodir); + (void)strcat(dirinfo, "/.Parent"); + fp = fopen(dirinfo, "w"); + if(fp == NULL) { + perror(dirinfo); + exit(1); + } + rsz = 0; + wr_appledouble_info(fp); + (void)fclose(fp); + } else { + fp = fopen(f_folder, "w"); + if(fp == NULL) { + perror(f_folder); + exit(1); + } + header[I_NAMEOFF] |= 0x80; + (void)fwrite(header, 1, INFOBYTES, fp); + header[I_NAMEOFF] &= 0x7f; + (void)fclose(fp); + } +#endif /* APPLEDOUBLE */ +#else /* APPLESHARE */ + fp = fopen(f_folder, "w"); + if(fp == NULL) { + perror(f_folder); + exit(1); + } + header[I_NAMEOFF] |= 0x80; + (void)fwrite(header, 1, INFOBYTES, fp); + header[I_NAMEOFF] &= 0x7f; + (void)fclose(fp); +#endif /* APPLESHARE */ +} + +void enddir() +{ +char header[INFOBYTES]; +int i; + +#ifndef SCAN + if(mode == MACS) { +#else /* SCAN */ + if(mode == MACS || mode == MACI) { +#endif /* SCAN */ + for(i = 0; i < INFOBYTES; i++) { + header[i] = 0; + } + header[I_NAMEOFF] = 0x80; + (void)fwrite(header, 1, INFOBYTES, stdout); + } else { + (void)chdir(".."); + } +} + +#ifdef APPLESHARE +#ifdef AUFS +static void check_aufs() +{ + /* check for .resource/ and .finderinfo/ */ + struct stat stbuf; + int error = 0; + + if(stat(rsrcdir,&stbuf) < 0) { + error ++; + } else { + if((stbuf.st_mode & S_IFMT) != S_IFDIR) { + error ++; + } + } + if(stat(infodir,&stbuf) < 0) { + error ++; + } else { + if((stbuf.st_mode & S_IFMT) != S_IFDIR) { + error++; + } + } + if(error) { + (void)fprintf(stderr, "Not in an Aufs folder.\n"); + exit(1); + } +} + +static void aufs_namings() +{ + mk_share_name(); + (void)sprintf(f_info_aufs, "%s/%s", infodir, share_name); + (void)sprintf(f_rsrc_aufs, "%s/%s", rsrcdir, share_name); + (void)sprintf(f_data, "%s", share_name); +} + +static void wr_aufs_info(fp) +FILE *fp; +{ + FileInfo theinfo; + int n; + + bzero((char *) &theinfo, sizeof theinfo); + theinfo.fi_magic1 = FI_MAGIC1; + theinfo.fi_version = FI_VERSION; + theinfo.fi_magic = FI_MAGIC; + theinfo.fi_bitmap = FI_BM_MACINTOSHFILENAME; + + /* AUFS stores Unix times. */ +#ifdef AUFSPLUS + theinfo.fi_datemagic = FI_MAGIC; + theinfo.fi_datevalid = FI_CDATE | FI_MDATE; + put4(theinfo.fi_ctime, get4(buffer + I_CTIMOFF) - TIMEDIFF); + put4(theinfo.fi_mtime, get4(buffer + I_MTIMOFF) - TIMEDIFF); + put4(theinfo.fi_utime, (unsigned long)time((time_t *)0)); +#endif /* AUFSPLUS */ + bcopy(buffer + I_TYPEOFF, theinfo.fi_fndr, 4); + bcopy(buffer + I_AUTHOFF, theinfo.fi_fndr + 4, 4); + bcopy(buffer + I_FLAGOFF, theinfo.fi_fndr + 8, 2); + if((n = buffer[I_NAMEOFF] & 0xff) > F_NAMELEN) { + n = F_NAMELEN; + } + (void)strncpy((char *)theinfo.fi_macfilename, buffer + I_NAMEOFF + 1,n); + /* theinfo.fi_macfilename[n] = '\0'; */ + (void)strcpy((char *)theinfo.fi_comnt, + "Converted by Unix utility to Aufs format"); + theinfo.fi_comln = strlen((char *)theinfo.fi_comnt); + (void)fwrite((char *) &theinfo, 1, sizeof theinfo, fp); +} +#endif /* AUFS */ + +#ifdef APPLEDOUBLE +static void check_appledouble() +{ + /* check for .AppleDouble/ */ + struct stat stbuf; + int error = 0; + + if(stat(infodir,&stbuf) < 0) { + error ++; + } else { + if((stbuf.st_mode & S_IFMT) != S_IFDIR) { + error++; + } + } + if(error) { + (void)fprintf(stderr, "Not in an AppleDouble folder.\n"); + exit(1); + } +} + +static void appledouble_namings() +{ + mk_share_name(); + (void)sprintf(f_info_appledouble, "%s/%s", infodir, share_name); + (void)sprintf(f_data, "%s", share_name); +} + +static void wr_appledouble_info(fp) +FILE *fp; +{ + FileInfo theinfo; + int n; + + bzero((char *) &theinfo, sizeof theinfo); + put4(theinfo.fi_magic, (unsigned long)FI_MAGIC); + put2(theinfo.fi_version, (unsigned long)FI_VERSION); + put4(theinfo.fi_fill5, (unsigned long)FI_FILL5); + put4(theinfo.fi_fill6, (unsigned long)FI_FILL6); + put4(theinfo.fi_hlen, (unsigned long)FI_HLEN); + put4(theinfo.fi_fill7, (unsigned long)FI_FILL7); + put4(theinfo.fi_namptr, (unsigned long)FI_NAMPTR); + put4(theinfo.fi_fill9, (unsigned long)FI_FILL9); + put4(theinfo.fi_commptr, (unsigned long)FI_COMMPTR); + put4(theinfo.fi_fill12, (unsigned long)FI_FILL12); + put4(theinfo.fi_timeptr, (unsigned long)FI_TIMEPTR); + put4(theinfo.fi_timesize, (unsigned long)FI_TIMESIZE); + put4(theinfo.fi_fill15, (unsigned long)FI_FILL15); + put4(theinfo.fi_infoptr, (unsigned long)FI_INFOPTR); + put4(theinfo.fi_infosize, (unsigned long)FI_INFOSIZE); + + bcopy(buffer + I_TYPEOFF, theinfo.fi_type, 4); + bcopy(buffer + I_AUTHOFF, theinfo.fi_auth, 4); + bcopy(buffer + I_FLAGOFF, theinfo.fi_finfo, 2); + /* AppleDouble stores Unix times. */ + put4(theinfo.fi_ctime, get4(buffer + I_CTIMOFF) - TIMEDIFF); + put4(theinfo.fi_mtime, get4(buffer + I_MTIMOFF) - TIMEDIFF); + if((n = buffer[I_NAMEOFF] & 0xff) > F_NAMELEN) { + n = F_NAMELEN; + } + put4(theinfo.fi_namlen, (unsigned long)n); + (void)strncpy((char *)theinfo.fi_name, buffer + I_NAMEOFF + 1,n); + /* theinfo.fi_macfilename[n] = '\0'; */ + (void)strcpy((char *)theinfo.fi_comment, + "Converted by Unix utility to AppleDouble format"); + put4(theinfo.fi_commsize, (unsigned long)strlen(theinfo.fi_comment)); + put4(theinfo.fi_rsrc, (unsigned long)rsz); + /* Still TODO */ + /* char fi_ctime[4]; /* Creation time (Unix time) */ + /* char fi_mtime[4]; /* Modification time (Unix time) */ + (void)fwrite((char *) &theinfo, 1, sizeof theinfo, fp); +} +#endif /* APPLEDOUBLE */ + +static void mk_share_name() +{ + int ch; + char *mp, *up; + + mp = buffer + 2; + up = &(share_name[0]); + while(ch = *mp++) { + if(isascii(ch) && ! iscntrl(ch) && isprint(ch) && ch != '/') { + *up++ = ch; + } else { + *up++ = ':'; + *up++ = hex[(ch >> 4) & 0xf]; + *up++ = hex[ch & 0xf]; + } + } + *up = 0; +} +#endif /* APPLESHARE */ + +int wrfileopt(c) +char c; +{ + switch(c) { + case 'b': + mode = MACB; + break; + case 'r': + if(mode_restricted) { + return 0; + } + mode = RSRC; + break; + case 'd': + if(mode_restricted) { + return 0; + } + mode = DATA; + break; + case 'u': + if(mode_restricted) { + return 0; + } + mode = TEXT; + break; + case 'U': + if(mode_restricted) { + return 0; + } + mode = UNIX; + break; + case 'f': + mode = FORK; + break; + case '3': + mode = FULL; + break; + case 's': + if(mode_s_restricted) { + return 0; + } + mode = MACS; + break; +#ifdef SCAN + case 'S': + if(mode_s_restricted) { + return 0; + } + mode = MACI; + break; +#endif /* SCAN */ + case 'a': +#ifdef APPLESHARE +#ifdef AUFS + check_aufs(); + mode = APSH; + break; +#endif /* AUFS */ +#ifdef APPLEDOUBLE + check_appledouble(); + mode = APSH; + break; +#endif /* APPLEDOUBLE */ +#else /* APPLESHARE */ + (void)fprintf(stderr, "Sorry, Apple-Unix sharing is not supported.\n"); + (void)fprintf(stderr, "Recompile or omit -a option.\n"); + exit(1); +#endif /* APPLESHARE */ + default: + return 0; + } + return 1; +} + +void give_wrfileopt() +{ + (void)fprintf(stderr, "File output options:\n"); + (void)fprintf(stderr, "-b:\tMacBinary (default)\n"); + if(!mode_s_restricted) { + (void)fprintf(stderr, "-s:\tMacBinary stream to standard output\n"); +#ifdef SCAN + (void)fprintf(stderr, + "-S:\tas -s but with indication of orignal Unix filename\n"); +#endif /* SCAN */ + } + (void)fprintf(stderr, "-f:\tthree fork mode, skipping empty forks\n"); + (void)fprintf(stderr, "-3:\tthe same, writing also empty forks\n"); + if(!mode_restricted) { + (void)fprintf(stderr, "-r:\tresource forks only\n"); + (void)fprintf(stderr, "-d:\tdata forks only\n"); + (void)fprintf(stderr, + "-u:\tdata forks only with Mac -> Unix text file translation\n"); + (void)fprintf(stderr, + "-U:\tas -u, but filename will not have an extension\n"); + } +#ifdef APPLESHARE +#ifdef AUFS + (void)fprintf(stderr, "-a:\tAUFS format\n"); +#endif /* AUFS */ +#ifdef APPLEDOUBLE + (void)fprintf(stderr, "-a:\tAppleDouble format\n"); +#endif /* APPLEDOUBLE */ +#else /* APPLESHARE */ + (void)fprintf(stderr, "-a:\tnot supported, needs recompilation\n"); +#endif /* APPLESHARE */ +} + +void set_wrfileopt(restricted) +{ + mode_restricted = restricted; +} + +void set_s_wrfileopt(restricted) +{ + mode_s_restricted = restricted; +} + +char *get_wrfileopt() +{ + static char options[20]; + + (void)strcpy(options, "b"); + if(!mode_s_restricted) { + (void)strcat(options, "s"); +#ifdef SCAN + (void)strcat(options, "S"); +#endif /* SCAN */ + } + (void)strcat(options, "f3"); + if(!mode_restricted) { + (void)strcat(options, "rduU"); + } + (void)strcat(options, "a"); + return options; +} + +char *get_mina() +{ +#ifdef APPLESHARE +#ifdef AUFS + return ", AUFS supported"; +#endif /* AUFS */ +#ifdef APPLEDOUBLE + return ", AppleDouble supported"; +#endif /* APPLEDOUBLE */ +#else /* APPLESHARE */ + return ", no Apple-Unix sharing supported"; +#endif /* APPLESHARE */ +} + diff --git a/fileio/wrfile.h b/fileio/wrfile.h new file mode 100755 index 0000000..d069d14 --- /dev/null +++ b/fileio/wrfile.h @@ -0,0 +1,14 @@ +extern char *out_buffer, *out_ptr; + +extern void define_name(); +extern void start_info(); +extern void start_rsrc(); +extern void start_data(); +extern void end_file(); +#ifdef SCAN +extern void do_idf(); +#endif /* SCAN */ +extern void do_mkdir(); +extern void enddir(); +extern char *get_mina(); + diff --git a/fileio/wrfile.o b/fileio/wrfile.o new file mode 100644 index 0000000..6d6b7e0 Binary files /dev/null and b/fileio/wrfile.o differ diff --git a/fileio/wrfileopt.h b/fileio/wrfileopt.h new file mode 100755 index 0000000..da3083a --- /dev/null +++ b/fileio/wrfileopt.h @@ -0,0 +1,6 @@ +extern int wrfileopt(); +extern void give_wrfileopt(); +extern void set_wrfileopt(); +extern void set_s_wrfileopt(); +extern char *get_wrfileopt(); + diff --git a/hexbin/buffer.c b/hexbin/buffer.c new file mode 100755 index 0000000..501b4e8 --- /dev/null +++ b/hexbin/buffer.c @@ -0,0 +1,76 @@ +#include "globals.h" +#include "../util/util.h" +#include "buffer.h" +#include "../fileio/wrfile.h" + +extern char *malloc(); +extern char *realloc(); +extern void exit(); + +char *data_fork, *rsrc_fork; +int data_size, rsrc_size; +static int max_data_size, max_rsrc_size; +static int do_data; + +void put_byte(c) +char c; +{ + if(do_data) { + if(data_size >= max_data_size) { + if(max_data_size == 0) { + data_fork = malloc(1024); + } else { + data_fork = realloc(data_fork, (unsigned)max_data_size + 1024); + } + max_data_size += 1024; + if(data_fork == NULL) { + (void)fprintf(stderr, "Insufficient memory.\n"); + exit(1); + } + } + data_fork[data_size++] = c; + } else { + if(rsrc_size >= max_rsrc_size) { + if(max_rsrc_size == 0) { + rsrc_fork = malloc(1024); + } else { + rsrc_fork = realloc(rsrc_fork, (unsigned)max_rsrc_size + 1024); + } + max_rsrc_size += 1024; + if(rsrc_fork == NULL) { + (void)fprintf(stderr, "Insufficient memory.\n"); + exit(1); + } + } + rsrc_fork[rsrc_size++] = c; + } +} + +void set_put(data) +int data; +{ + do_data = data; + if(do_data) { + data_size = 0; + } else { + rsrc_size = 0; + } +} + +void end_put() +{ + if(info_only) { + return; + } + start_info(info, (unsigned long)rsrc_size, (unsigned long)data_size); + if(data_size != 0) { + start_data(); + copy(out_ptr, data_fork, data_size); + } + if(rsrc_size != 0) { + start_rsrc(); + copy(out_ptr, rsrc_fork, rsrc_size); + } + end_file(); +} + diff --git a/hexbin/buffer.h b/hexbin/buffer.h new file mode 100755 index 0000000..1bd2dfa --- /dev/null +++ b/hexbin/buffer.h @@ -0,0 +1,6 @@ +extern char *data_fork, *rsrc_fork; +extern int data_size, rsrc_size; +extern void put_byte(); +extern void set_put(); +extern void end_put(); + diff --git a/hexbin/crc.c b/hexbin/crc.c new file mode 100755 index 0000000..e5e59c0 --- /dev/null +++ b/hexbin/crc.c @@ -0,0 +1,44 @@ +/* crc.c; do crc calculation. */ + +#include +#include "hexbin.h" +#include "crc.h" +#include "../util/masks.h" +#include "globals.h" + +extern void exit(); + +unsigned long crc; + +#ifdef HQX +void comp_q_crc(c) +register unsigned int c; +{ + unsigned char cc = c; + + crc = binhex_updcrc(crc, &cc, 1); +} + +void comp_q_crc_n(s, e) +register unsigned char *s, *e; +{ + crc = binhex_updcrc(crc, s, e - s); +} +#endif /* HQX */ + +void verify_crc(calc_crc, file_crc) +unsigned long calc_crc, file_crc; +{ + calc_crc &= WORDMASK; + file_crc &= WORDMASK; + + if(calc_crc != file_crc) { + (void)fprintf(stderr, "CRC mismatch: got 0x%04lx, need 0x%04lx\n", + file_crc, calc_crc); +#ifdef SCAN + do_error("hexbin: CRC error"); +#endif /* SCAN */ + exit(1); + } +} + diff --git a/hexbin/crc.h b/hexbin/crc.h new file mode 100755 index 0000000..67e49fb --- /dev/null +++ b/hexbin/crc.h @@ -0,0 +1,10 @@ +#define INITCRC binhex_crcinit + +extern unsigned long crc; +extern unsigned long binhex_crcinit; +extern unsigned long binhex_updcrc(); + +extern void comp_q_crc(); +extern void comp_q_crc_n(); +extern void verify_crc(); + diff --git a/hexbin/dl.c b/hexbin/dl.c new file mode 100755 index 0000000..700c1cb --- /dev/null +++ b/hexbin/dl.c @@ -0,0 +1,134 @@ +#include "hexbin.h" +#ifdef DL +#include "globals.h" +#include "crc.h" +#include "readline.h" +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "../util/util.h" +#include "buffer.h" +#include "printhdr.h" + +extern void exit(); + +static long dl_fork(); +static int nchar(); +static int nextc(); + +static char *icp = &line[0]; + +/* oldest format -- process .dl files */ +void dl(macname, filename) +char *macname, *filename; +{ + int n; + + if(listmode) { + (void)fprintf(stderr, "This file is in \"dl\" format.\n"); + } + for(n = 0; n < INFOBYTES; n++) { + info[n] = 0; + } + /* set up for Mac name */ + if(macname[0] == '\0') { + /* strip directories */ + macname = search_last(filename, '/'); + if(macname == NULL) { + macname = filename; + } else { + macname++; + } + /* strip extension */ + n = strlen(macname); + if(n > 3) { + n -= 3; + if(!strncmp(macname + n, ".dl", 3)) { + macname[n] = '\0'; + } + } + } + n = strlen(macname); + if(n > F_NAMELEN) { + n = F_NAMELEN; + } + (void)strncpy(mh.m_name, macname, n); + (void)strncpy(mh.m_type, "APPL", 4); + (void)strncpy(mh.m_author, "????", 4); + mh.m_name[n] = '\0'; + transname(mh.m_name, trname, n); + define_name(trname); + print_header0(0); + print_header1(0, 0); + set_put(1); + mh.m_datalen = 0; + set_put(0); + mh.m_rsrclen = dl_fork(); + info[I_NAMEOFF] = n; + (void)strncpy(info + I_NAMEOFF + 1, mh.m_name, n); + (void)strncpy(info + I_TYPEOFF, mh.m_type, 4); + (void)strncpy(info + I_AUTHOFF, mh.m_author, 4); + put4(info + I_DLENOFF, (unsigned long)mh.m_datalen); + put4(info + I_RLENOFF, (unsigned long)mh.m_rsrclen); + put4(info + I_CTIMOFF, (unsigned long)mh.m_createtime); + put4(info + I_MTIMOFF, (unsigned long)mh.m_modifytime); + print_header2(0); + end_put(); +} + +static long dl_fork() +{ + register unsigned long i, v, c; + register unsigned long n, bytes; + + n = 0; + bytes = 0; + v = 0; + crc = 0; + while((i = nchar()) != '|') { + if(i < '@' || i > 'O') { + continue; + } + v = (v << 4) | (i & 0xF); + if((++n & 1) == 0) { + put_byte((char)v); + crc += v; + v = 0; + bytes++; + } + } + c = 0; + for(i = 0 ; i < 8 ; i++) { + c = (c << 4) | (nchar() & 0xF); + } + verify_crc(bytes + crc, c); + return bytes; +} + +static int nchar() +{ + int i; + + if((i = nextc()) == EOF) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("hexbin: Premature EOF"); +#endif /* SCAN */ + exit(1); + } + return i & 0177; +} + +static int nextc() +{ + while(*icp == 0) { + if(readline() == 0) { + return EOF; + } + icp = &line[0]; + } + return *icp++; +} +#else /* DL */ +int dl; /* keep lint and some compilers happy */ +#endif /* DL */ + diff --git a/hexbin/globals.c b/hexbin/globals.c new file mode 100755 index 0000000..91b3961 --- /dev/null +++ b/hexbin/globals.c @@ -0,0 +1,27 @@ +#include "globals.h" +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "../fileio/kind.h" + +struct macheader mh; + +char info[INFOBYTES]; +char trname[64]; + +int listmode; +int info_only; +int verbose; +int uneven_lines; +int to_read; +int was_macbin; + +FILE *ifp; + +#ifdef SCAN +void do_error(string) +char *string; +{ + do_idf(string, ERROR); +} +#endif /* SCAN */ + diff --git a/hexbin/globals.h b/hexbin/globals.h new file mode 100755 index 0000000..d22e9d5 --- /dev/null +++ b/hexbin/globals.h @@ -0,0 +1,39 @@ +#include +#include +#ifdef BSD +extern char *rindex(); +#define search_last rindex +#else /* BSD */ +extern char *strrchr(); +#define search_last strrchr +#endif /* BSD */ + +extern void transname(); + +extern char info[]; +extern char trname[]; + +typedef struct macheader { + char m_name[128]; + char m_type[4]; + char m_author[4]; + short m_flags; + long m_datalen; + long m_rsrclen; + long m_createtime; + long m_modifytime; +}; + +extern struct macheader mh; + +extern int listmode; +extern int verbose; +extern int info_only; +extern int uneven_lines; +extern int to_read; +extern int was_macbin; + +extern FILE *ifp; + +extern void do_error(); + diff --git a/hexbin/hecx.c b/hexbin/hecx.c new file mode 100755 index 0000000..5d19d8e --- /dev/null +++ b/hexbin/hecx.c @@ -0,0 +1,256 @@ +#include "hexbin.h" +#ifdef HECX +#include "globals.h" +#include "crc.h" +#include "readline.h" +#include "../util/masks.h" +#include "../util/util.h" +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "buffer.h" +#include "printhdr.h" + +extern void exit(); + +static void do_o_forks(); +static long make_file(); +static void comp_c_crc(); +static void comp_e_crc(); +static int comp_to_bin(); +static int hex_to_bin(); +static int hexit(); + +static int compressed; + +/* old format -- process .hex and .hcx files */ +void hecx(macname, filename) +char *macname, *filename; +{ + int n; + + for(n = 0; n < INFOBYTES; n++) { + info[n] = 0; + } + compressed = 0; + /* set up name for output files */ + if(macname[0] == '\0') { + /* strip directories */ + macname = search_last(filename, '/'); + if(macname == NULL) { + macname = filename; + } else { + macname++; + } + + /* strip extension */ + n = strlen(macname); + if(n > 4) { + n -= 4; + if(!strncmp(macname + n, ".hex", 4) || + !strncmp(macname + n, ".hcx", 4)) { + macname[n] = '\0'; + } + } + } + n = strlen(macname); + if(n > F_NAMELEN) { + n = F_NAMELEN; + } + (void)strncpy(mh.m_name, macname, n); + mh.m_name[n] = '\0'; + + /* "#TYPEAUTH$flag" line already read */ + n = strlen(line); + if(n >= 6 && line[0] == '#' && line[n-5] == '$') { + if(n >= 10) { + (void)strncpy(mh.m_type, &line[1], 4); + } + if(n >= 14) { + (void)strncpy(mh.m_author, &line[5], 4); + } + (void)sscanf(&line[n-4], "%4hx", &mh.m_flags); + } + transname(mh.m_name, trname, n); + define_name(trname); + do_o_forks(); + if(listmode) { + if(!compressed) { + (void)fprintf(stderr, "This file is in \"hex\" format.\n"); + } else { + (void)fprintf(stderr, "This file is in \"hcx\" format.\n"); + } + } + print_header0(0); + print_header1(0, 0); + info[I_NAMEOFF] = n; + (void)strncpy(info + I_NAMEOFF + 1, mh.m_name, n); + (void)strncpy(info + I_TYPEOFF, mh.m_type, 4); + (void)strncpy(info + I_AUTHOFF, mh.m_author, 4); + put2(info + I_FLAGOFF, (unsigned long)mh.m_flags); + put4(info + I_DLENOFF, (unsigned long)mh.m_datalen); + put4(info + I_RLENOFF, (unsigned long)mh.m_rsrclen); + put4(info + I_CTIMOFF, (unsigned long)mh.m_createtime); + put4(info + I_MTIMOFF, (unsigned long)mh.m_modifytime); + print_header2(0); + end_put(); +} + +static void do_o_forks() +{ + int forks = 0, found_crc = 0; + unsigned long calc_crc, file_crc; + + crc = 0; /* calculate a crc for both forks */ + + set_put(0); + set_put(1); + while(!found_crc && readline()) { + if(line[0] == 0) { + continue; + } + if(forks == 0 && strncmp(line, "***COMPRESSED", 13) == 0) { + compressed++; + continue; + } + if(strncmp(line, "***DATA", 7) == 0) { + set_put(1); + mh.m_datalen = make_file(compressed); + forks++; + continue; + } + if(strncmp(line, "***RESOURCE", 11) == 0) { + set_put(0); + mh.m_rsrclen = make_file(compressed); + forks++; + continue; + } + if(compressed && strncmp(line, "***CRC:", 7) == 0) { + found_crc++; + calc_crc = crc; + (void)sscanf(&line[7], "%lx", &file_crc); + break; + } + if(!compressed && strncmp(line, "***CHECKSUM:", 12) == 0) { + found_crc++; + calc_crc = crc & BYTEMASK; + (void)sscanf(&line[12], "%lx", &file_crc); + file_crc &= BYTEMASK; + break; + } + } + + if(found_crc) { + verify_crc(calc_crc, file_crc); + } else { + (void)fprintf(stderr, "missing CRC\n"); +#ifdef SCAN + do_error("hexbin: missing CRC"); +#endif /* SCAN */ + exit(1); + } +} + +static long make_file(compressed) +int compressed; +{ + register long nbytes = 0L; + + while(readline()) { + if(line[0] == 0) { + continue; + } + if(strncmp(line, "***END", 6) == 0) { + break; + } + if(compressed) { + nbytes += comp_to_bin(); + } else { + nbytes += hex_to_bin(); + } + } + return nbytes; +} + +static void comp_c_crc(c) +unsigned char c; +{ + crc = (crc + c) & WORDMASK; + crc = ((crc << 3) & WORDMASK) | (crc >> 13); +} + +static void comp_e_crc(c) +unsigned char c; +{ + crc += c; +} + +#define SIXB(c) (((c)-0x20) & 0x3f) + +static int comp_to_bin() +{ + char obuf[BUFSIZ]; + register char *ip = line; + register char *op = obuf; + register int n, outcount; + int numread, incount; + + numread = strlen(line); + outcount = (SIXB(ip[0]) << 2) | (SIXB(ip[1]) >> 4); + incount = ((outcount / 3) + 1) * 4; + for(n = numread; n < incount; n++) { /* restore lost spaces */ + line[n] = ' '; + } + + n = 0; + while(n <= outcount) { + *op++ = SIXB(ip[0]) << 2 | SIXB(ip[1]) >> 4; + *op++ = SIXB(ip[1]) << 4 | SIXB(ip[2]) >> 2; + *op++ = SIXB(ip[2]) << 6 | SIXB(ip[3]); + ip += 4; + n += 3; + } + + for(n = 1; n <= outcount; n++) { + comp_c_crc((unsigned)obuf[n]); + put_byte(obuf[n]); + } + return outcount; +} + +static int hex_to_bin() +{ + register char *ip = line; + register int n, outcount; + int c; + + n = strlen(line); + outcount = n / 2; + for(n = 0; n < outcount; n++) { + c = hexit((int)*ip++); + comp_e_crc((unsigned)(c = (c << 4) | hexit((int)*ip++))); + put_byte((char)c); + } + return outcount; +} + +static int hexit(c) +int c; +{ + if('0' <= c && c <= '9') { + return c - '0'; + } + if('A' <= c && c <= 'F') { + return c - 'A' + 10; + } + + (void)fprintf(stderr, "illegal hex digit: %c", c); +#ifdef SCAN + do_error("hexbin: illegal hex digit"); +#endif /* SCAN */ + exit(1); + /* NOTREACHED */ +} +#else /* HECX */ +int hecx; /* keep lint and some compilers happy */ +#endif /* HECX */ + diff --git a/hexbin/hexbin.c b/hexbin/hexbin.c new file mode 100755 index 0000000..a730858 --- /dev/null +++ b/hexbin/hexbin.c @@ -0,0 +1,362 @@ +#ifdef TYPES_H +#include +#endif /* TYPES_H */ +#include +#include "globals.h" +#include "crc.h" +#include "readline.h" +#include "../util/masks.h" +#include "../util/util.h" +#include "../util/patchlevel.h" +#include "../fileio/wrfile.h" +#include "../fileio/wrfileopt.h" +#include "../fileio/machdr.h" +#include "../fileio/kind.h" +#include "../util/curtime.h" +#include "hexbin.h" + +#define LOCALOPT "ilvcn:qVH" + +extern void exit(); +extern void backtrans(); +#ifdef DL +extern void dl(); +#endif /* DL */ +#ifdef HECX +extern void hecx(); +#endif /* HECX */ +#ifdef HQX +extern void hqx(); +#endif /* HQX */ +#ifdef MU +extern void mu(); +#endif /* MU */ + +static void usage(); +static void do_files(); +static int find_header(); + +static char options[128]; + +int main(argc, argv) +int argc; +char **argv; +{ + char *filename; + char macname[32]; + extern int optind; + extern char *optarg; + int errflg; + int c; + + set_wrfileopt(0); + (void)strcat(options, get_wrfileopt()); + (void)strcat(options, LOCALOPT); + errflg = 0; + filename = ""; + macname[0] = 0; + + while((c = getopt(argc, argv, options)) != EOF) { + if(!wrfileopt((char)c)) { + switch(c) { + case 'l': + listmode++; + break; + case 'v': + verbose++; + break; + case 'i': + info_only++; + break; + case 'c': + uneven_lines++; + break; + case 'n': + backtrans(macname, optarg); + break; + case '?': + errflg++; + break; + case 'H': + give_wrfileopt(); + (void)fprintf(stderr, "Hexbin specific options:\n"); + (void)fprintf(stderr, + "-i:\tgive information only, do not convert\n"); + (void)fprintf(stderr, "-l:\tgive listing\n"); + (void)fprintf(stderr, + "-v:\tgive verbose listing, including lines skipped\n"); + (void)fprintf(stderr, + "-c:\tdo not check for equal line lengths\n"); + (void)fprintf(stderr, "-n nm:\tname to be generated\n"); + (void)fprintf(stderr, + "-V:\tgive information about this version\n"); + (void)fprintf(stderr, "-H:\tthis message\n"); + (void)fprintf(stderr, "Default is silent conversion\n"); + exit(0); + case 'V': + (void)fprintf(stderr, "Version %s, ", VERSION); + (void)fprintf(stderr, "patchlevel %d", PATCHLEVEL); + (void)fprintf(stderr, "%s.\n", get_mina()); + (void)fprintf(stderr, "Hexified files recognized:\n"); +#ifdef DL + (void)fprintf(stderr, "\tDownload (.dl)\n"); +#endif /* DL */ +#ifdef HECX + (void)fprintf(stderr, "\tBinHex 2.0 (.hex)\n"); + (void)fprintf(stderr, "\tBinHex 3.0 (.hcx)\n"); +#endif /* HECX */ +#ifdef HQX + (void)fprintf(stderr, "\tBinHex 4.0 (.hqx)\n"); +#endif /* HQX */ +#ifdef MU + (void)fprintf(stderr, "\tUUTool (.mu)\n"); +#endif /* MU */ + exit(0); + } + } + } + if(errflg) { + usage(); + exit(1); + } + if(info_only || verbose) { + listmode++; + } + + do { + if(optind == argc) { + filename = "-"; + } else { + filename = argv[optind]; + optind++; +#ifdef SCAN + do_idf(filename, UNIX_NAME); +#endif /* SCAN */ + } + do_files(filename, macname); + } while(optind < argc); + exit(0); + /* NOTREACHED */ +} + +static char *extensions[] = { +#ifdef DL + ".dl", +#endif /* DL */ +#ifdef HECX + ".hex", + ".Hex", + ".hcx", + ".Hcx", +#endif /* HECX */ +#ifdef HQX + ".hqx", + ".Hqx", +#endif /* HQX */ +#ifdef MU + ".mu", +#endif /* MU */ + "", + NULL +}; + +static void do_files(filename, macname) +char *filename; /* input file name -- extension optional */ +char *macname; /* name to use on the mac side of things */ +{ + char namebuf[256]; + char **ep; + struct stat stbuf; + long curtime; + int qformat; + int again; + + if(filename[0] == '-') { + ifp = stdin; + filename = "stdin"; + } else { + /* find input file and open it */ + for(ep = extensions; *ep != NULL; ep++) { + (void)sprintf(namebuf, "%s%s", filename, *ep); + if(stat(namebuf, &stbuf) == 0) { + break; + } + } + if(*ep == NULL) { + perror(namebuf); + exit(1); + } + ifp = fopen(namebuf, "r"); + if(ifp == NULL) { + perror(namebuf); + exit(1); + } + } + again = 0; +nexttry: + if(ifp == stdin) { + curtime = (long)time((time_t *)0) + TIMEDIFF; + mh.m_createtime = curtime; + mh.m_modifytime = curtime; + } else { + mh.m_createtime = stbuf.st_mtime + TIMEDIFF; + mh.m_modifytime = stbuf.st_mtime + TIMEDIFF; + } + + qformat = find_header(again); /* eat mailer header &cetera, intuit format */ + + switch (qformat) { +#ifdef DL + case form_dl: + dl(macname, filename); + break; +#endif /* DL */ +#ifdef HECX + case form_hecx: + hecx(macname, filename); + break; +#endif /* HECX */ +#ifdef HQX + case form_hqx: + hqx(macname); + again = 1; + goto nexttry; +#endif /* HQX */ +#ifdef MU + case form_mu: + mu(macname); + again = 1; + goto nexttry; +#endif /* MU */ + default: + break; + } + (void)fclose(ifp); +} + +/* eat characters until header detected, return which format */ +static int find_header(again) +int again; +{ + int c, dl_start, llen; + char *cp; + char header[INFOBYTES]; + int ds, rs; + + if(again && was_macbin) { + while(to_read-- > 0) { + c = fgetc(ifp); + } + } + was_macbin = 0; + c = fgetc(ifp); + (void)ungetc(c, ifp); + if(c == 0) { + was_macbin = 1; + if(fread(header, 1, INFOBYTES, ifp) != INFOBYTES) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("hexbin: Premature EOF"); +#endif /* SCAN */ + exit(1); + } + ds = get4(header + I_DLENOFF); + rs = get4(header + I_RLENOFF); + ds = (((ds + 127) >> 7) << 7); + rs = (((rs + 127) >> 7) << 7); + to_read = ds + rs; + if(strncmp(header + I_TYPEOFF, "TEXT", 4)) { + (void)fprintf(stderr, "This file is not a proper BinHexed file.\n"); +#ifdef SCAN + do_error("hexbin: not a proper BinHexed file"); +#endif /* SCAN */ + exit(1); + } + if(listmode) { + (void)fprintf(stderr, "This file is probably packed by "); + if(!strncmp(header + I_AUTHOFF, "BNHQ", 4)) { + (void)fprintf(stderr, "\"BinHex\""); + } else if(!strncmp(header + I_AUTHOFF, "BthX", 4)) { + (void)fprintf(stderr, "\"BinHqx\""); + } else if(!strncmp(header + I_AUTHOFF, "BnHq", 4)) { + (void)fprintf(stderr, "\"StuffIt\""); + } else if(!strncmp(header + I_AUTHOFF, "ttxt", 4)) { + (void)fprintf(stderr, "\"Compactor\""); + } else if(!strncmp(header + I_AUTHOFF, "BSWU", 4)) { + (void)fprintf(stderr, "\"UUTool\""); + } else { + (void)fprintf(stderr, "an unknown program"); + } + (void)fprintf(stderr, ".\n"); + } + } + /* look for "(This file ...)" or "(Convert with...)" line. */ + /* or for "begin " */ + /* dl format starts with a line containing only the symbols '@' to 'O', + or '|'. */ + while(readline()) { + llen = strlen(line); +#ifdef HQX + if((strncmp(line, "(This file", 10) == 0) || + (strncmp(line, "(Convert with", 13) == 0)) { + if(verbose) { + (void)fprintf(stderr, "Skip:%s\n", line); + } + break; + } +#endif /* HQX */ +#ifdef MU + if(strncmp(line, "begin ", 6) == 0) { + return form_mu; + } +#endif /* MU */ +#ifdef DL + /* Do not allow bogus false starts */ + if(llen > 40 && (llen & 1) == 0) { + dl_start = 1; + for(cp = &line[0]; *cp != 0; cp++) { + if((*cp < '@' || *cp > 'O') && *cp != '|') { + dl_start = 0; + break; + } + } + if(dl_start && cp > &line[1]) { + return form_dl; + } + } +#endif /* DL */ + if(llen != 0 && verbose) { + (void)fprintf(stderr, "Skip:%s\n", line); + } + } + while(readline()) { + switch (line[0]) { +#ifdef HQX + case ':': + return form_hqx; +#endif /* HQX */ +#ifdef HECX + case '#': + return form_hecx; +#endif /* HECX */ + default: + break; + } + } + + if(!again) { + (void)fprintf(stderr, "unexpected EOF\n"); +#ifdef SCAN + do_error("hexbin: unexpected EOF"); +#endif /* SCAN */ + exit(1); + } + return form_none; +} + +static void usage() +{ + (void)fprintf(stderr, "Usage: hexbin [-%s] [filenames]\n", options); + (void)fprintf(stderr, "Use \"hexbin -H\" for help.\n"); +} + diff --git a/hexbin/hexbin.h b/hexbin/hexbin.h new file mode 100755 index 0000000..3df0af0 --- /dev/null +++ b/hexbin/hexbin.h @@ -0,0 +1,11 @@ +#define DL /* recognize dl format */ +#define HECX /* recognize hex and hcx formats */ +#define HQX /* recognize hqx format */ +#define MU /* recognize mu format */ + +#define form_dl 0 +#define form_hecx 1 +#define form_hqx 2 +#define form_mu 3 +#define form_none (-1) + diff --git a/hexbin/hqx.c b/hexbin/hqx.c new file mode 100755 index 0000000..e998626 --- /dev/null +++ b/hexbin/hqx.c @@ -0,0 +1,396 @@ +#include "hexbin.h" +#ifdef HQX +#include "globals.h" +#include "readline.h" +#include "crc.h" +#include "buffer.h" +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "../util/util.h" +#include "printhdr.h" + +extern void exit(); + +static void get_header(); +static void oflush(); +static int getq(); +static long get2q(); +static long get4q(); +static getqbuf(); + +static char *g_macname; + +/* New stuff which hopes to improve the speed. */ + +#define RUNCHAR 0x90 + +#define DONE 0x7F +#define SKIP 0x7E +#define FAIL 0x7D + +static char lookup[256] = { +/* ^@ ^A ^B ^C ^D ^E ^F ^G */ +/* 0*/ FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, +/* \b \t \n ^K ^L \r ^N ^O */ +/* 1*/ FAIL, FAIL, SKIP, FAIL, FAIL, SKIP, FAIL, FAIL, +/* ^P ^Q ^R ^S ^T ^U ^V ^W */ +/* 2*/ FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, +/* ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */ +/* 3*/ FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, +/* ! " # $ % & ' */ +/* 4*/ FAIL, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, +/* ( ) * + , - . / */ +/* 5*/ 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, FAIL, FAIL, +/* 0 1 2 3 4 5 6 7 */ +/* 6*/ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, FAIL, +/* 8 9 : ; < = > ? */ +/* 7*/ 0x14, 0x15, DONE, FAIL, FAIL, FAIL, FAIL, FAIL, +/* @ A B C D E F G */ +/* 8*/ 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, +/* H I J K L M N O */ +/* 9*/ 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, FAIL, +/* P Q R S T U V W */ +/*10*/ 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, FAIL, +/* X Y Z [ \ ] ^ _ */ +/*11*/ 0x2C, 0x2D, 0x2E, 0x2F, FAIL, FAIL, FAIL, FAIL, +/* ` a b c d e f g */ +/*12*/ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, FAIL, +/* h i j k l m n o */ +/*13*/ 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, FAIL, FAIL, +/* p q r s t u v w */ +/*14*/ 0x3D, 0x3E, 0x3F, FAIL, FAIL, FAIL, FAIL, FAIL, +/* x y z { | } ~ ^? */ +/*15*/ FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, +/*16*/ FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, +}; + +static int stop = 0; + +static unsigned char obuf[BUFSIZ]; +static unsigned char *op = obuf; +static unsigned char *oq; + +#define S_HEADER 0 +#define S_DATAOPEN 1 +#define S_DATAWRITE 2 +#define S_DATAC1 3 +#define S_DATAC2 4 +#define S_RSRCOPEN 5 +#define S_RSRCWRITE 6 +#define S_RSRCC1 7 +#define S_RSRCC2 8 +#define S_EXCESS 9 + +static int ostate = S_HEADER; + +static unsigned long calc_crc; +static unsigned long file_crc; + +static long todo; + +#define output(c) { *op++ = (c); if(op >= &obuf[BUFSIZ]) oflush(); } + +void hqx(macname) +char *macname; +{ + int n, normlen, c; + register char *in, *out; + register int b6, b8, data, lastc = 0; + char state68 = 0, run = 0, linestate, first = 1; + + g_macname = macname; + + ostate = S_HEADER; + stop = 0; + + while(!stop) { + n = strlen((char *)line); + while(n > 0 && line[n - 1] == ' ') { + n--; + } + out = line+n; + if(uneven_lines) { + goto skipcheck; + } + if(first) { + normlen = n; + } + /* Check line for intermediate garbage */ + linestate = SKIP; + for(in = line; in < out; in++) { + if((linestate = lookup[*in & 0xff]) == FAIL || + ((linestate == DONE) && !first)) { + break; + } + } + if(linestate != FAIL && n != normlen && linestate != DONE) { + c = fgetc(ifp); + (void)ungetc(c, ifp); + if(lookup[c] == DONE) { + linestate = DONE; + } + } + if(linestate == FAIL || (n != normlen && linestate != DONE)) { + if(verbose && n > 0) { + *out = 0; + (void)fprintf(stderr, "Skip:%s\n", line); + } + if(readline()) { + continue; + } else { + break; + } + } +skipcheck: + in = line; + do { + if((b6 = lookup[*in & 0xff]) >= 64) { + switch (b6) { + case DONE: + first = !first; + if(first) { + goto done; + } + case SKIP: + break; + default: + if(uneven_lines) { + break; + } + (void)fprintf(stderr, "bad char '%c'(%d)\n", *in, *in); + goto done; + } + } else { + /* Pack 6 bits to 8 bits */ + switch (state68++) { + case 0: + b8 = b6<<2; + continue; /* No data byte */ + case 1: + data = b8 | (b6>>4); + b8 = (b6&0xF) << 4; + break; + case 2: + data = b8 | (b6>>2); + b8 = (b6&0x3) << 6; + break; + case 3: + data = b8 | b6; + state68 = 0; + break; + } + if(!run) { + if(data == RUNCHAR) { + run = 1; + } else { + output(lastc = data); + } + } + else { + if(data == 0) { + output(lastc = RUNCHAR); + } else { + while(--data > 0) { + output(lastc); + } + } + run = 0; + } + } + } while(++in < out); + if(!stop) { + if(!readline()) { + break; + } + } + } +done: + oflush(); + if(!stop && ostate != S_EXCESS) { + (void)fprintf(stderr, "premature EOF\n"); +#ifdef SCAN + do_error("hexbin: premature EOF"); +#endif /* SCAN */ + exit(1); + } + end_put(); + print_header2(verbose); +} + +static void get_header() +{ + int n; + unsigned long calc_crc, file_crc; + + crc = INITCRC; /* compute a crc for the header */ + + for(n = 0; n < INFOBYTES; n++) { + info[n] = 0; + } + n = getq(); /* namelength */ + n++; /* must read trailing null also */ + getqbuf(trname, n); /* read name */ + if(g_macname[0] == '\0') { + g_macname = trname; + } + + n = strlen(g_macname); + if(n > F_NAMELEN) { + n = F_NAMELEN; + } + (void)strncpy(mh.m_name, g_macname, n); + mh.m_name[n] = '\0'; + + getqbuf(mh.m_type, 4); + getqbuf(mh.m_author, 4); + mh.m_flags = get2q(); + mh.m_datalen = get4q(); + mh.m_rsrclen = get4q(); + + calc_crc = crc; + file_crc = get2q(); + verify_crc(calc_crc, file_crc); + if(listmode) { + (void)fprintf(stderr, "This file is in \"hqx\" format.\n"); + } + transname(mh.m_name, trname, n); + define_name(trname); + print_header0(0); + print_header1(0, verbose); + info[I_NAMEOFF] = n; + (void)strncpy(info + I_NAMEOFF + 1, mh.m_name, n); + (void)strncpy(info + I_TYPEOFF, mh.m_type, 4); + (void)strncpy(info + I_AUTHOFF, mh.m_author, 4); + put2(info + I_FLAGOFF, (unsigned long)mh.m_flags); + put4(info + I_DLENOFF, (unsigned long)mh.m_datalen); + put4(info + I_RLENOFF, (unsigned long)mh.m_rsrclen); + put4(info + I_CTIMOFF, (unsigned long)mh.m_createtime); + put4(info + I_MTIMOFF, (unsigned long)mh.m_modifytime); +} + +static void oflush() +{ + int n, i; + + oq = obuf; + while(oq < op && !stop) { + switch (ostate) { + case S_HEADER: + get_header(); + ++ostate; + break; + case S_DATAOPEN: + set_put(1); + todo = mh.m_datalen; + crc = INITCRC; + ++ostate; + break; + case S_RSRCOPEN: + set_put(0); + todo = mh.m_rsrclen; + crc = INITCRC; + ++ostate; + break; + case S_DATAWRITE: + case S_RSRCWRITE: + n = op-oq; + if(n > todo) { + n = todo; + } + for(i = 0; i < n; i++) { + put_byte((char)(oq[i])); + } + comp_q_crc_n(oq, oq+n); + oq += n; + todo -= n; + if(todo <= 0) { + ++ostate; + } + break; + case S_DATAC1: + case S_RSRCC1: + calc_crc = crc; + file_crc = getq() << 8; + ++ostate; + break; + case S_DATAC2: + case S_RSRCC2: + /* Skip crc bytes */ + file_crc |= getq(); + verify_crc(calc_crc, file_crc); + ++ostate; + break; + case S_EXCESS: + (void)fprintf(stderr, "%d excess bytes ignored\n", op-oq); + oq = op; + break; + } + } + op = obuf; +} + +static int getq() +{ + int c; + + if(oq >= op) { + (void)fprintf(stderr, "premature EOF\n"); +#ifdef SCAN + do_error("hexbin: premature EOF"); +#endif /* SCAN */ + exit(1); + } + c = *oq++ & 0xff; + comp_q_crc((unsigned)c); + return c; +} + +/* get2q(); q format -- read 2 bytes from input, return short */ +static long get2q() +{ + short high = getq() << 8; + return high | getq(); +} + +/* get4q(); q format -- read 4 bytes from input, return long */ +static long get4q() +{ + int i; + long value = 0; + + for(i = 0; i < 4; i++) { + value = (value<<8) | getq(); + } + return value; +} + +/* getqbuf(); q format -- read n characters from input into buf */ +static getqbuf(buf, n) + char *buf; + int n; +{ + int i; + + for(i = 0; i < n; i++) { + *buf++ = getq(); + } +} +#else /* HQX */ +int hqx; /* keep lint and some compilers happy */ +#endif /* HQX */ + diff --git a/hexbin/hqx.diff b/hexbin/hqx.diff new file mode 100755 index 0000000..0f15aec --- /dev/null +++ b/hexbin/hqx.diff @@ -0,0 +1,35 @@ +*** hqx.c Mon Mar 9 21:36:57 1992 +--- n.hqx.c Mon Mar 9 22:07:53 1992 +*************** +*** 108,114 **** + void hqx(macname) + char *macname; + { +! int n, normlen; + register char *in, *out; + register int b6, b8, data, lastc = 0; + char state68 = 0, run = 0, linestate, first = 1; +--- 108,114 ---- + void hqx(macname) + char *macname; + { +! int n, normlen, c; + register char *in, *out; + register int b6, b8, data, lastc = 0; + char state68 = 0, run = 0, linestate, first = 1; +*************** +*** 136,141 **** +--- 136,148 ---- + if((linestate = lookup[*in & 0xff]) == FAIL || + ((linestate == DONE) && !first)) { + break; ++ } ++ } ++ if(linestate != FAIL && n != normlen && linestate != DONE) { ++ c = fgetc(ifp); ++ (void)ungetc(c, ifp); ++ if(lookup[c] == DONE) { ++ linestate = DONE; + } + } + if(linestate == FAIL || (n != normlen && linestate != DONE)) { diff --git a/hexbin/makefile b/hexbin/makefile new file mode 100755 index 0000000..898df05 --- /dev/null +++ b/hexbin/makefile @@ -0,0 +1,130 @@ +CFLAGS= -O $(CF) + +SRCS = hexbin.c \ + dl.c \ + hecx.c \ + hqx.c \ + mu.c \ + buffer.c \ + crc.c \ + readline.c \ + printhdr.c \ + globals.c + +OBJS = hexbin.o \ + dl.o \ + hecx.o \ + hqx.o \ + mu.o \ + buffer.o \ + crc.o \ + readline.o \ + printhdr.o \ + globals.o + +LIB = ../crc/libcrc.a +TNAME = ../util/transname +BNAME = ../util/backtrans +UNAME = ../util/util +ONAME = ../fileio/wrfile +GNAME = ../fileio/fileglob +XOBJS = $(TNAME).o $(BNAME).o $(UNAME).o $(ONAME).o $(GNAME).o +XSRCS = $(TNAME).c $(BNAME).c $(UNAME).c $(ONAME).c $(GNAME).c +CRCS = ../crc/binhex.c + +hexbin: $(OBJS) $(LIB) $(XOBJS) + $(CC) $(CFLAGS) -o hexbin $(OBJS) $(XOBJS) $(LIB) + +$(LIB): ../crc/makecrc.c + (cd ../crc; make CC=$(CC) CF="$(CF)" ) + +$(TNAME).o: $(TNAME).c + (cd ../util; make CC=$(CC) CF="$(CF)" ) + +$(BNAME).o: $(BNAME).c + (cd ../util; make CC=$(CC) CF="$(CF)" ) + +$(UNAME).o: $(UNAME).c + (cd ../util; make CC=$(CC) CF="$(CF)" ) + +$(ONAME).o: $(ONAME).c + (cd ../fileio; make CC=$(CC) CF="$(CF)" ) + +$(GNAME).o: $(GNAME).c + (cd ../fileio; make CC=$(CC) CF="$(CF)" ) + +lint: + lint $(CF) $(LFLAGS) $(SRCS) $(XSRCS) $(CRCS) + +clean: + -rm -f *.o + +clobber:clean + -rm -f hexbin + +hexbin.o: globals.h +hexbin.o: crc.h +hexbin.o: readline.h +hexbin.o: ../util/masks.h +hexbin.o: ../util/util.h +hexbin.o: ../util/patchlevel.h +hexbin.o: ../fileio/wrfile.h +hexbin.o: ../fileio/wrfileopt.h +hexbin.o: ../fileio/machdr.h +hexbin.o: ../fileio/kind.h +hexbin.o: ../util/curtime.h +hexbin.o: hexbin.h +dl.o: hexbin.h +dl.o: globals.h +dl.o: crc.h +dl.o: readline.h +dl.o: ../fileio/machdr.h +dl.o: ../fileio/wrfile.h +dl.o: ../util/util.h +dl.o: buffer.h +dl.o: printhdr.h +hecx.o: hexbin.h +hecx.o: globals.h +hecx.o: crc.h +hecx.o: readline.h +hecx.o: ../util/masks.h +hecx.o: ../util/util.h +hecx.o: ../fileio/machdr.h +hecx.o: ../fileio/wrfile.h +hecx.o: buffer.h +hecx.o: printhdr.h +hqx.o: hexbin.h +hqx.o: globals.h +hqx.o: readline.h +hqx.o: crc.h +hqx.o: buffer.h +hqx.o: ../fileio/machdr.h +hqx.o: ../fileio/wrfile.h +hqx.o: ../util/util.h +hqx.o: printhdr.h +mu.o: hexbin.h +mu.o: globals.h +mu.o: readline.h +mu.o: ../util/masks.h +mu.o: ../util/util.h +mu.o: ../fileio/machdr.h +mu.o: ../fileio/wrfile.h +mu.o: buffer.h +mu.o: printhdr.h +buffer.o: globals.h +buffer.o: ../util/util.h +buffer.o: buffer.h +buffer.o: ../fileio/wrfile.h +crc.o: hexbin.h +crc.o: crc.h +crc.o: ../util/masks.h +crc.o: globals.h +readline.o: readline.h +readline.o: globals.h +printhdr.o: printhdr.h +printhdr.o: globals.h +globals.o: globals.h +globals.o: ../fileio/machdr.h +globals.o: ../fileio/wrfile.h +globals.o: ../fileio/kind.h + diff --git a/hexbin/mu.c b/hexbin/mu.c new file mode 100755 index 0000000..8b43c48 --- /dev/null +++ b/hexbin/mu.c @@ -0,0 +1,225 @@ +#include "hexbin.h" +#ifdef MU +#include "globals.h" +#include "readline.h" +#include "../util/masks.h" +#include "../util/util.h" +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "buffer.h" +#include "printhdr.h" + +extern void exit(); + +static void do_mu_fork(); +static int mu_comp_to_bin(); +static int mu_convert(); + +/* mu format -- process .mu files */ +void mu(macname) +char *macname; +{ + int n; + + for(n = 0; n < INFOBYTES; n++) { + info[n] = 0; + } + + /* set up name for output files */ + if(macname[0] == '\0') { + n = 0; + while(line[n] != '"') { + n++; + } + macname = line + n + 1; + line[strlen(line) - 1] = 0; + } + n = strlen(macname); + if(n > F_NAMELEN) { + n = F_NAMELEN; + } + (void)strncpy(mh.m_name, macname, n); + mh.m_name[n] = '\0'; + info[I_NAMEOFF] = n; + (void)strncpy(info + I_NAMEOFF + 1, mh.m_name, n); + + if(listmode) { + (void)fprintf(stderr, "This file is in \"mu\" format.\n"); + } + transname(mh.m_name, trname, n); + define_name(trname); + print_header0(0); + set_put(0); + set_put(1); + do_mu_fork(); + mh.m_datalen = data_size; + if(!readline()) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("hexbin: Premature EOF"); +#endif /* SCAN */ + exit(1); + } + if(strncmp(line, "begin ", 6)) { + (void)fprintf(stderr, "No UU header found.\n"); +#ifdef SCAN + do_error("hexbin: No UU header found"); +#endif /* SCAN */ + exit(1); + } + if(!strncmp(line + 10, " .rsrc", 6)) { + set_put(0); + do_mu_fork(); + mh.m_rsrclen = rsrc_size; + if(!readline()) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("hexbin: Premature EOF"); +#endif /* SCAN */ + exit(1); + } + if(strncmp(line, "begin ", 6)) { + (void)fprintf(stderr, "No UU header found.\n"); +#ifdef SCAN + do_error("hexbin: No UU header found"); +#endif /* SCAN */ + exit(1); + } + } else { + mh.m_rsrclen = 0; + } + if(strncmp(line + 10, " .finfo", 7)) { + (void)fprintf(stderr, "No finder info found.\n"); +#ifdef SCAN + do_error("hexbin: No finder info found"); +#endif /* SCAN */ + exit(1); + } + if(!readline()) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("hexbin: Premature EOF"); +#endif /* SCAN */ + exit(1); + } + (void)mu_convert(line, info + I_TYPEOFF); + if(!readline()) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("hexbin: Premature EOF"); +#endif /* SCAN */ + exit(1); + } + if(mu_convert(line, line)) { + (void)fprintf(stderr, "Long finderinfo.\n"); +#ifdef SCAN + do_error("hexbin: Long finderinfo"); +#endif /* SCAN */ + exit(1); + } + if(!readline()) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("hexbin: Premature EOF"); +#endif /* SCAN */ + exit(1); + } + if(strncmp(line, "end", 3)) { + (void)fprintf(stderr, "\"end\" line missing.\n"); +#ifdef SCAN + do_error("hexbin: \"end\" line missing"); +#endif /* SCAN */ + exit(1); + } + + (void)strncpy(mh.m_type, info + I_TYPEOFF, 4); + (void)strncpy(mh.m_author, info + I_AUTHOFF, 4); + print_header1(0, 0); + put4(info + I_DLENOFF, (unsigned long)mh.m_datalen); + put4(info + I_RLENOFF, (unsigned long)mh.m_rsrclen); + put4(info + I_CTIMOFF, (unsigned long)mh.m_createtime); + put4(info + I_MTIMOFF, (unsigned long)mh.m_modifytime); + print_header2(0); + end_put(); +} + +static void do_mu_fork() +{ + long newbytes; + + while(readline()) { + if(line[0] == 0) { + continue; + } + newbytes = mu_comp_to_bin(); + if(newbytes != 0) { + continue; + } + if(!readline()) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("hexbin: Premature EOF"); +#endif /* SCAN */ + exit(1); + } + if(strncmp(line, "end", 3)) { + (void)fprintf(stderr, "\"end\" line missing.\n"); +#ifdef SCAN + do_error("hexbin: \"end\" line missing"); +#endif /* SCAN */ + exit(1); + } + return; + } + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("hexbin: Premature EOF"); +#endif /* SCAN */ + exit(1); + /*NOTREACHED*/ +} + +static int mu_comp_to_bin() +{ + char obuf[BUFSIZ]; + int outcount, n; + + outcount = mu_convert(line, obuf); + for(n = 0; n < outcount; n++) { + put_byte(obuf[n]); + } + return outcount; +} + +#define SIXB(c) (((c)-0x20) & 0x3f) + +static int mu_convert(ibuf, obuf) +char *ibuf, *obuf; +{ + register char *ip = ibuf; + register char *op = obuf; + register int n, outcount; + int numread, incount; + + numread = strlen(ip); + outcount = SIXB(ip[0]); + incount = ((outcount / 3) + 1) * 4; + for(n = numread; n < incount; n++) { /* restore lost spaces */ + ip[n] = ' '; + } + ip++; + + n = 0; + while(n <= outcount) { + *op++ = SIXB(ip[0]) << 2 | SIXB(ip[1]) >> 4; + *op++ = SIXB(ip[1]) << 4 | SIXB(ip[2]) >> 2; + *op++ = SIXB(ip[2]) << 6 | SIXB(ip[3]); + ip += 4; + n += 3; + } + return outcount; +} +#else /* MU */ +int mu; /* keep lint and some compilers happy */ +#endif /* MU */ + diff --git a/hexbin/printhdr.c b/hexbin/printhdr.c new file mode 100755 index 0000000..aa3f22f --- /dev/null +++ b/hexbin/printhdr.c @@ -0,0 +1,46 @@ +#include "printhdr.h" +#include "globals.h" + +/* print out header information in human-readable format */ +void print_header0(skip) +int skip; +{ + if(listmode) { + (void)fprintf(stderr, "name=\"%s\", ", trname); + if(skip) { + (void)fprintf(stderr, "\n"); + } + } +} + +/* print out header information in human-readable format */ +void print_header1(skip1, skip2) +int skip1, skip2; +{ + char ftype[5], fauth[5]; + + transname(mh.m_type, ftype, 4); + transname(mh.m_author, fauth, 4); + if(listmode) { + if(skip1) { + (void)fprintf(stderr, "\t"); + } + (void)fprintf(stderr, "type=%4.4s, author=%4.4s, ", ftype, fauth); + if(skip2) { + (void)fprintf(stderr, "\n"); + } + } +} + +/* print out header information in human-readable format */ +void print_header2(skip) +{ + if(listmode) { + if(skip) { + (void)fprintf(stderr, "\t"); + } + (void)fprintf(stderr, "data=%ld, rsrc=%ld\n", + mh.m_datalen, mh.m_rsrclen); + } +} + diff --git a/hexbin/printhdr.h b/hexbin/printhdr.h new file mode 100755 index 0000000..2cda600 --- /dev/null +++ b/hexbin/printhdr.h @@ -0,0 +1,4 @@ +extern void print_header0(); +extern void print_header1(); +extern void print_header2(); + diff --git a/hexbin/readline.c b/hexbin/readline.c new file mode 100755 index 0000000..9ebe6f1 --- /dev/null +++ b/hexbin/readline.c @@ -0,0 +1,40 @@ +#include "globals.h" +#include "readline.h" + +char line[1024]; /* Allow a lot! */ + +/* Read a line. Allow termination by CR or LF or both. Also allow for + a non-terminated line at end-of-file. Returns 1 if a line is read, + 0 otherwise. */ +int readline() +{ + int ptr = 0, c; + + while(1) { + if(was_macbin && to_read-- <= 0) { + c = EOF; + } else { + c = getc(ifp); + } + if(c == EOF || c == '\n' || c == '\r' || ptr == 1023) { + break; + } + line[ptr++] = c; + } + line[ptr++] = 0; + if(c == EOF) { + if(ptr == 1) { + return 0; + } else { + return 1; + } + } + c = getc(ifp); + if(c != '\n' || c != '\r') { + (void)ungetc(c, ifp); + } else { + to_read--; + } + return 1; +} + diff --git a/hexbin/readline.h b/hexbin/readline.h new file mode 100755 index 0000000..af379fa --- /dev/null +++ b/hexbin/readline.h @@ -0,0 +1,2 @@ +extern char line[]; + diff --git a/macunpack/arc.h b/macunpack/arc.h new file mode 100755 index 0000000..59c7f8e --- /dev/null +++ b/macunpack/arc.h @@ -0,0 +1,51 @@ +#define MAGIC1 0 /* Should be 0x1b, marks Mac extension */ +#define KIND 1 /* KIND == 0 marks end of archive */ +#define FNAME 2 +#define FILLER 33 +#define FTYPE 34 +#define FAUTH 38 +#define FINFO 42 +#define FDATA 50 +#define FRSRC 54 +#define FILLER 58 +#define MAGIC2 59 /* Should be 0x1a, true Arc header start */ +#define KIND2 60 /* Should be identical to KIND */ +#define FNAME2 61 /* A PC-ified version of the filename */ +#define SIZE 74 +#define DATE 78 +#define TIME 80 +#define CRC 82 +#define SIZE2 84 /* Not present if KIND == 1 */ +#define HEADERBYTES 88 + +typedef struct fileHdr { /* 84 or 88 bytes */ + char magic1; + char kind; + char fname[31]; + char filler; /* ??? */ + char ftype[4]; + char fauth[4]; + char finfo[8]; + unsigned long dataLength; + unsigned long rsrcLength; + char filler; + char magic2; + char kind2; + char fname2[13]; + unsigned long size; + unsigned short date; + unsigned short time; + unsigend short crc; + unsigned long size2; /* Identical to size; this is wrong for Arc! */ +}; + +#define smallstored 1 +#define stored 2 +#define packed 3 +#define squeezed 4 +#define crunched1 5 +#define crunched2 6 +#define crunched3 7 +#define crunched4 8 +#define squashed 9 + diff --git a/macunpack/bin.c b/macunpack/bin.c new file mode 100755 index 0000000..86fb1f0 --- /dev/null +++ b/macunpack/bin.c @@ -0,0 +1,68 @@ +#include "macunpack.h" +#ifdef BIN +#include "globals.h" +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "../fileio/kind.h" +#include "../util/util.h" +#include "../util/masks.h" + +extern void mcb(); + +void bin(header, data_size, UMcp) +char *header; +int data_size, UMcp; +{ + char hdr[INFOBYTES]; + unsigned long rsrcLength, dataLength; + + hdr[0] = getb(infp); + (void)ungetc(hdr[0], infp); + if(hdr[0] != 0) { + if(!strncmp(header + I_AUTHOFF, "BnHq", 4) && hdr[0] == '(') { + do_indent(indent); + (void)fprintf(stderr, "Sorry, this is a fake BinHex 5.0 file. "); + (void)fprintf(stderr, "Debinhex with hexbin first.\n"); +#ifdef SCAN + do_error("macunpack: fake BinHex 5.0"); +#endif /* SCAN */ + } else { + do_indent(indent); + (void)fprintf(stderr, "Sorry, contents not recognized.\n"); +#ifdef SCAN + do_error("macunpack: contents not recognized"); +#endif /* SCAN */ + } + do_indent(indent); + (void)fprintf(stderr, "Copying as a plain file.\n"); +#ifdef SCAN + do_idf("", COPY); +#endif /* SCAN */ + mcb(header, (unsigned long)in_data_size, (unsigned long)in_rsrc_size, + in_ds + in_rs); + ds_skip = 0; + rs_skip = 0; + in_ds = 0; + in_rs = 0; + return; + } + if(fread(hdr, 1, INFOBYTES - 1, infp) != INFOBYTES) { + (void)fprintf(stderr, "Can't read file header\n"); +#ifdef SCAN + do_error("macunpack: Can't read file header"); +#endif /* SCAN */ + exit(1); + } + rsrcLength = get4(hdr + I_RLENOFF); + dataLength = get4(hdr + I_DLENOFF); + if(UMcp) { + /* Why this? Moreover, we are losing the bundle bit! */ + put4(hdr + I_RLENOFF, ++rsrcLength); + put4(hdr + I_DLENOFF, ++dataLength); + } + mcb(hdr, rsrcLength, dataLength, data_size - INFOBYTES); +} +#else /* BIN */ +int bin; /* keep lint and some compilers happy */ +#endif /* BIN */ + diff --git a/macunpack/bin.o b/macunpack/bin.o new file mode 100644 index 0000000..bb7246a Binary files /dev/null and b/macunpack/bin.o differ diff --git a/macunpack/bits_be.c b/macunpack/bits_be.c new file mode 100755 index 0000000..e4ce810 --- /dev/null +++ b/macunpack/bits_be.c @@ -0,0 +1,46 @@ +#include "../util/masks.h" +#include "bits_be.h" + +unsigned int bit_be_bitbuf; +char *bit_be_filestart; +int bit_be_inbytes; + +static unsigned int bit_be_subbitbuf; +static int bit_be_bitcount; + +void bit_be_fillbuf(n) /* Shift bit_be_bitbuf n bits left, read n bits */ +int n; +{ + bit_be_bitbuf <<= n; + while (n > bit_be_bitcount) { + bit_be_bitbuf |= bit_be_subbitbuf << (n -= bit_be_bitcount); + if(bit_be_inbytes == 0) { + bit_be_subbitbuf = 0; + } else { + bit_be_subbitbuf = *bit_be_filestart++ & BYTEMASK; + bit_be_inbytes--; + } + bit_be_bitcount = 8; + } + bit_be_bitbuf |= bit_be_subbitbuf >> (bit_be_bitcount -= n); + bit_be_bitbuf &= WORDMASK; +} + +unsigned int bit_be_getbits(n) +int n; +{ + unsigned int x; + + x = bit_be_bitbuf >> (BITBUFSIZ - n); + bit_be_fillbuf(n); + return x; +} + +void bit_be_init_getbits() +{ + bit_be_bitbuf = 0; + bit_be_subbitbuf = 0; + bit_be_bitcount = 0; + bit_be_fillbuf(BITBUFSIZ); +} + diff --git a/macunpack/bits_be.h b/macunpack/bits_be.h new file mode 100755 index 0000000..3f8e549 --- /dev/null +++ b/macunpack/bits_be.h @@ -0,0 +1,10 @@ +#define BITBUFSIZ 16 + +extern unsigned int bit_be_bitbuf; +extern char *bit_be_filestart; +extern int bit_be_inbytes; + +extern void bit_be_fillbuf(); +extern unsigned int bit_be_getbits(); +extern void bit_be_init_getbits(); + diff --git a/macunpack/cpt.c b/macunpack/cpt.c new file mode 100755 index 0000000..5514302 --- /dev/null +++ b/macunpack/cpt.c @@ -0,0 +1,719 @@ +#include "macunpack.h" +#ifdef DD +#ifndef CPT +#define CPT +#endif /* CPT */ +#endif /* DD */ +#ifdef CPT +#include "globals.h" +#include "cpt.h" +#include "crc.h" +#include "../util/util.h" +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "../fileio/kind.h" +#include "../util/masks.h" +#include "huffman.h" + +#define ESC1 0x81 +#define ESC2 0x82 +#define NONESEEN 0 +#define ESC1SEEN 1 +#define ESC2SEEN 2 + +extern char *malloc(); +extern char *realloc(); +extern int free(); + +static void cpt_uncompact(); +static unsigned char *cpt_data; +static unsigned long cpt_datamax; +static unsigned long cpt_datasize; +static unsigned char cpt_LZbuff[CIRCSIZE]; +static unsigned int cpt_LZptr; +static unsigned char *cpt_char; +static unsigned long cpt_crc; +static unsigned long cpt_inlength; +static unsigned long cpt_outlength; +static int cpt_outstat; +static unsigned char cpt_savechar; +static unsigned long cpt_newbits; +static int cpt_bitsavail; +static int cpt_blocksize; +/* Lengths is twice the max number of entries, and include slack. */ +#define SLACK 6 +static node cpt_Hufftree[512 + SLACK], cpt_LZlength[128 + SLACK], + cpt_LZoffs[256 + SLACK]; + +static int readcpthdr(); +static int cpt_filehdr(); +static void cpt_folder(); +static void cpt_uncompact(); +static void cpt_wrfile(); +void cpt_wrfile1(); +static void cpt_outch(); +static void cpt_rle(); +static void cpt_rle_lzh(); +static void cpt_readHuff(); +static int cpt_get6bits(); +static int cpt_getbit(); + +void cpt() +{ + struct cptHdr cpthdr; + struct fileHdr filehdr; + char *cptindex; + int cptindsize; + char *cptptr; + int i; + + updcrc = zip_updcrc; + crcinit = zip_crcinit; + cpt_crc = INIT_CRC; + if(readcpthdr(&cpthdr) == 0) { + (void)fprintf(stderr, "Can't read archive header\n"); +#ifdef SCAN + do_error("macunpack: Can't read archive header"); +#endif /* SCAN */ + exit(1); + } + + cptindsize = cpthdr.entries * FILEHDRSIZE; + if(cpthdr.commentsize > cptindsize) { + cptindsize = cpthdr.commentsize; + } + cptindex = malloc((unsigned)cptindsize); + if(cptindex == NULL) { + (void)fprintf(stderr, "Insufficient memory, aborting\n"); + exit(1); + } + cptptr = cptindex; + if(fread(cptptr, 1, (int)cpthdr.commentsize, infp) != cpthdr.commentsize) { + (void)fprintf(stderr, "Can't read comment.\n"); +#ifdef SCAN + do_error("macunpack: Can't read comment"); +#endif /* SCAN */ + exit(1); + } + cpt_crc = (*updcrc)(cpt_crc, cptptr, cpthdr.commentsize); + + for(i = 0; i < cpthdr.entries; i++) { + *cptptr = getc(infp); + cpt_crc = (*updcrc)(cpt_crc, cptptr, 1); + if(*cptptr & 0x80) { + cptptr[F_FOLDER] = 1; + *cptptr &= 0x3f; + } else { + cptptr[F_FOLDER] = 0; + } + if(fread(cptptr + 1, 1, *cptptr, infp) != *cptptr) { + (void)fprintf(stderr, "Can't read file header #%d\n", i+1); +#ifdef SCAN + do_error("macunpack: Can't read file header"); +#endif /* SCAN */ + exit(1); + } + cpt_crc = (*updcrc)(cpt_crc, cptptr + 1, *cptptr); + if(cptptr[F_FOLDER]) { + if(fread(cptptr + F_FOLDERSIZE, 1, 2, infp) != 2) { + (void)fprintf(stderr, "Can't read file header #%d\n", i+1); +#ifdef SCAN + do_error("macunpack: Can't read file header"); +#endif /* SCAN */ + exit(1); + } + cpt_crc = (*updcrc)(cpt_crc, cptptr + F_FOLDERSIZE, 2); + } else { + if(fread(cptptr + F_VOLUME, 1, FILEHDRSIZE - F_VOLUME, infp) != + FILEHDRSIZE - F_VOLUME) { + (void)fprintf(stderr, "Can't read file header #%d\n", i+1); +#ifdef SCAN + do_error("macunpack: Can't read file header"); +#endif /* SCAN */ + exit(1); + } + cpt_crc = (*updcrc)(cpt_crc, cptptr + F_VOLUME, + FILEHDRSIZE - F_VOLUME); + } + cptptr += FILEHDRSIZE; + } + if(cpt_crc != cpthdr.hdrcrc) { + (void)fprintf(stderr, "Header CRC mismatch: got 0x%08x, need 0x%08x\n", + (int)cpthdr.hdrcrc, (int)cpt_crc); +#ifdef SCAN + do_error("macunpack: Header CRC mismatch"); +#endif /* SCAN */ + exit(1); + } + + cptptr = cptindex; + for(i = 0; i < cpthdr.entries; i++) { + if(cpt_filehdr(&filehdr, cptptr) == -1) { + (void)fprintf(stderr, "Can't read file header #%d\n", i+1); +#ifdef SCAN + do_error("macunpack: Can't read file header"); +#endif /* SCAN */ + exit(1); + } + if(filehdr.folder) { + cpt_folder(text, filehdr, cptptr); + i += filehdr.foldersize; + cptptr += filehdr.foldersize * FILEHDRSIZE; + } else { + cpt_uncompact(filehdr); + } + cptptr += FILEHDRSIZE; + } + (void)free(cptindex); +} + +static int readcpthdr(s) +struct cptHdr *s; +{ + char temp[CHDRSIZE]; + + if(fread(temp, 1, CPTHDRSIZE, infp) != CPTHDRSIZE) { + return 0; + } + + if(temp[C_SIGNATURE] != 1) { + (void)fprintf(stderr, "Not a Compactor file\n"); + return 0; + } + + cpt_datasize = get4(temp + C_IOFFSET); + s->offset = cpt_datasize; + if(cpt_datasize > cpt_datamax) { + if(cpt_datamax == 0) { + cpt_data = (unsigned char *)malloc((unsigned)cpt_datasize); + } else { + cpt_data = (unsigned char *)realloc((char *)cpt_data, + (unsigned)cpt_datasize); + } + cpt_datamax = cpt_datasize; + } + if(cpt_data == NULL) { + (void)fprintf(stderr, "Insufficient memory, aborting\n"); + exit(1); + } + + if(fread((char *)(cpt_data + CPTHDRSIZE), 1, + (int)s->offset - CPTHDRSIZE, infp) != s->offset - CPTHDRSIZE) { + return 0; + } + + if(fread(temp + CPTHDRSIZE, 1, CPTHDR2SIZE, infp) != CPTHDR2SIZE) { + return 0; + } + + cpt_crc = (*updcrc)(cpt_crc, temp + CPTHDRSIZE + C_ENTRIES, 3); + s->hdrcrc = get4(temp + CPTHDRSIZE + C_HDRCRC); + s->entries = get2(temp + CPTHDRSIZE + C_ENTRIES); + s->commentsize = temp[CPTHDRSIZE + C_COMMENT]; + + return 1; +} + +static int cpt_filehdr(f, hdr) +struct fileHdr *f; +char *hdr; +{ + register int i; + int n; + char ftype[5], fauth[5]; + + for(i = 0; i < INFOBYTES; i++) { + info[i] = '\0'; + } + + n = hdr[F_FNAME] & BYTEMASK; + if(n > F_NAMELEN) { + n = F_NAMELEN; + } + info[I_NAMEOFF] = n; + copy(info + I_NAMEOFF + 1, hdr + F_FNAME + 1, n); + transname(hdr + F_FNAME + 1, text, n); + + f->folder = hdr[F_FOLDER]; + if(f->folder) { + f->foldersize = get2(hdr + F_FOLDERSIZE); + } else { + f->cptFlag = get2(hdr + F_CPTFLAG); + f->rsrcLength = get4(hdr + F_RSRCLENGTH); + f->dataLength = get4(hdr + F_DATALENGTH); + f->compRLength = get4(hdr + F_COMPRLENGTH); + f->compDLength = get4(hdr + F_COMPDLENGTH); + f->fileCRC = get4(hdr + F_FILECRC); + f->FndrFlags = get2(hdr + F_FNDRFLAGS); + f->filepos = get4(hdr + F_FILEPOS); + f->volume = hdr[F_VOLUME]; + } + + write_it = 1; + if(list) { + do_indent(indent); + if(f->folder) { + (void)fprintf(stderr, "folder=\"%s\"", text); + } else { + transname(hdr + F_FTYPE, ftype, 4); + transname(hdr + F_CREATOR, fauth, 4); + (void)fprintf(stderr, + "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld", + text, ftype, fauth, + (long)f->dataLength, (long)f->rsrcLength); + } + if(info_only) { + write_it = 0; + } + if(query) { + write_it = do_query(); + } else { + (void)fputc('\n', stderr); + } + } + + + if(write_it) { + define_name(text); + + if(!f->folder) { + copy(info + I_TYPEOFF, hdr + F_FTYPE, 4); + copy(info + I_AUTHOFF, hdr + F_CREATOR, 4); + copy(info + I_FLAGOFF, hdr + F_FNDRFLAGS, 2); + copy(info + I_DLENOFF, hdr + F_DATALENGTH, 4); + copy(info + I_RLENOFF, hdr + F_RSRCLENGTH, 4); + copy(info + I_CTIMOFF, hdr + F_CREATIONDATE, 4); + copy(info + I_MTIMOFF, hdr + F_MODDATE, 4); + } + } + return 1; +} + +static void cpt_folder(name, fileh, cptptr) +char *name; +struct fileHdr fileh; +char *cptptr; +{ + int i, nfiles; + char loc_name[64]; + struct fileHdr filehdr; + + for(i = 0; i < 64; i++) { + loc_name[i] = name[i]; + } + if(write_it || info_only) { + cptptr += FILEHDRSIZE; + nfiles = fileh.foldersize; + if(write_it) { + do_mkdir(text, info); + } + indent++; + for(i = 0; i < nfiles; i++) { + if(cpt_filehdr(&filehdr, cptptr) == -1) { + (void)fprintf(stderr, "Can't read file header #%d\n", i+1); +#ifdef SCAN + do_error("macunpack: Can't read file header"); +#endif /* SCAN */ + exit(1); + } + if(filehdr.folder) { + cpt_folder(text, filehdr, cptptr); + i += filehdr.foldersize; + cptptr += filehdr.foldersize * FILEHDRSIZE; + } else { + cpt_uncompact(filehdr); + } + cptptr += FILEHDRSIZE; + } + if(write_it) { + enddir(); + } + indent--; + if(list) { + do_indent(indent); + (void)fprintf(stderr, "leaving folder \"%s\"\n", loc_name); + } + } +} + +static void cpt_uncompact(filehdr) +struct fileHdr filehdr; +{ + if(filehdr.cptFlag & 1) { + (void)fprintf(stderr, "\tFile is password protected, skipping file\n"); +#ifdef SCAN + do_idf("", PROTECTED); +#endif /* SCAN */ + return; + } + if(write_it) { + start_info(info, filehdr.rsrcLength, filehdr.dataLength); + cpt_crc = INIT_CRC; + cpt_char = cpt_data + filehdr.filepos; + } + if(verbose) { + (void)fprintf(stderr, "\tRsrc: "); + if(filehdr.compRLength == 0) { + (void)fprintf(stderr, "empty"); + } else if(filehdr.cptFlag & 2) { + (void)fprintf(stderr, "RLE/LZH compressed (%4.1f%%)", + 100.0 * filehdr.compRLength / filehdr.rsrcLength); + } else { + (void)fprintf(stderr, "RLE compressed (%4.1f%%)", + 100.0 * filehdr.compRLength / filehdr.rsrcLength); + } + } + if(write_it) { + start_rsrc(); + cpt_wrfile(filehdr.compRLength, filehdr.rsrcLength, + filehdr.cptFlag & 2); + cpt_char = cpt_data + filehdr.filepos + filehdr.compRLength; + } + if(verbose) { + (void)fprintf(stderr, ", Data: "); + if(filehdr.compDLength == 0) { + (void)fprintf(stderr, "empty"); + } else if(filehdr.cptFlag & 4) { + (void)fprintf(stderr, "RLE/LZH compressed (%4.1f%%)", + 100.0 * filehdr.compDLength / filehdr.dataLength); + } else { + (void)fprintf(stderr, "RLE compressed (%4.1f%%)", + 100.0 * filehdr.compDLength / filehdr.dataLength); + } + } + if(write_it) { + start_data(); + cpt_wrfile(filehdr.compDLength, filehdr.dataLength, + filehdr.cptFlag & 4); + if(filehdr.fileCRC != cpt_crc) { + (void)fprintf(stderr, + "CRC error on file: need 0x%08lx, got 0x%08lx\n", + (long)filehdr.fileCRC, (long)cpt_crc); +#ifdef SCAN + do_error("macunpack: CRC error on file"); +#endif /* SCAN */ + exit(1); + } + end_file(); + } + if(verbose) { + (void)fprintf(stderr, ".\n"); + } +} + +static void cpt_wrfile(ibytes, obytes, type) +unsigned long ibytes, obytes; +unsigned short type; +{ + if(ibytes == 0) { + return; + } + cpt_outstat = NONESEEN; + cpt_inlength = ibytes; + cpt_outlength = obytes; + cpt_LZptr = 0; + cpt_blocksize = 0x1fff0; + if(type == 0) { + cpt_rle(); + } else { + cpt_rle_lzh(); + } + cpt_crc = (*updcrc)(cpt_crc, out_buffer, obytes); +} + +void cpt_wrfile1(in_char, ibytes, obytes, type, blocksize) +unsigned char *in_char; +unsigned long ibytes, obytes, blocksize; +int type; +{ + cpt_char = in_char; + if(ibytes == 0) { + return; + } + cpt_outstat = NONESEEN; + cpt_inlength = ibytes; + cpt_outlength = obytes; + cpt_LZptr = 0; + cpt_blocksize = blocksize; + if(type == 0) { + cpt_rle(); + } else { + cpt_rle_lzh(); + } +} + +static void cpt_outch(ch) +unsigned char ch; +{ + cpt_LZbuff[cpt_LZptr++ & (CIRCSIZE - 1)] = ch; + switch(cpt_outstat) { + case NONESEEN: + if(ch == ESC1 && cpt_outlength != 1) { + cpt_outstat = ESC1SEEN; + } else { + cpt_savechar = ch; + *out_ptr++ = ch; + cpt_outlength--; + } + break; + case ESC1SEEN: + if(ch == ESC2) { + cpt_outstat = ESC2SEEN; + } else { + cpt_savechar = ESC1; + *out_ptr++ = ESC1; + cpt_outlength--; + if(cpt_outlength == 0) { + return; + } + if(ch == ESC1 && cpt_outlength != 1) { + return; + } + cpt_outstat = NONESEEN; + cpt_savechar = ch; + *out_ptr++ = ch; + cpt_outlength--; + } + break; + case ESC2SEEN: + cpt_outstat = NONESEEN; + if(ch != 0) { + while(--ch != 0) { + *out_ptr++ = cpt_savechar; + cpt_outlength--; + if(cpt_outlength == 0) { + return; + } + } + } else { + *out_ptr++ = ESC1; + cpt_outlength--; + if(cpt_outlength == 0) { + return; + } + cpt_savechar = ESC2; + *out_ptr++ = cpt_savechar; + cpt_outlength--; + } + } +} + +/*---------------------------------------------------------------------------*/ +/* Run length encoding */ +/*---------------------------------------------------------------------------*/ +static void cpt_rle() +{ + while(cpt_inlength-- > 0) { + cpt_outch(*cpt_char++); + } +} + +/*---------------------------------------------------------------------------*/ +/* Run length encoding plus LZ compression plus Huffman encoding */ +/*---------------------------------------------------------------------------*/ +static void cpt_rle_lzh() +{ + int block_count; + unsigned int bptr; + int Huffchar, LZlength, LZoffs; + + get_bit = cpt_getbit; + cpt_LZbuff[CIRCSIZE - 3] = 0; + cpt_LZbuff[CIRCSIZE - 2] = 0; + cpt_LZbuff[CIRCSIZE - 1] = 0; + cpt_LZptr = 0; + while(cpt_outlength != 0) { + cpt_readHuff(256, cpt_Hufftree); + cpt_readHuff(64, cpt_LZlength); + cpt_readHuff(128, cpt_LZoffs); + block_count = 0; + cpt_newbits = (*cpt_char++ << 8); + cpt_newbits = cpt_newbits | *cpt_char++; + cpt_newbits = cpt_newbits << 16; + cpt_bitsavail = 16; + while(block_count < cpt_blocksize && cpt_outlength != 0) { + if(cpt_getbit()) { + Huffchar = gethuffbyte(cpt_Hufftree); + cpt_outch((unsigned char)Huffchar); + block_count += 2; + } else { + LZlength = gethuffbyte(cpt_LZlength); + LZoffs = gethuffbyte(cpt_LZoffs); + LZoffs = (LZoffs << 6) | cpt_get6bits(); + bptr = cpt_LZptr - LZoffs; + while(LZlength-- > 0) { + cpt_outch(cpt_LZbuff[bptr++ & (CIRCSIZE - 1)]); + } + block_count += 3; + } + } + } +} + +/* Based on unimplod from unzip; difference are noted below. */ +typedef struct sf_entry { + int Value; + int BitLength; +} sf_entry; + +/* See routine LoadTree. The parameter tree (actually an array and + two integers) are only used locally in this version and hence locally + declared. The parameter nodes has been renamed Hufftree.... */ +static void cpt_readHuff(size, Hufftree) +int size; +struct node *Hufftree; +{ + sf_entry tree_entry[256 + SLACK]; /* maximal number of elements */ + int tree_entries; + int tree_MaxLength; /* finishes local declaration of tree */ + + int treeBytes, i, len; /* declarations from ReadLengths */ + + /* declarations from SortLengths */ + sf_entry *ejm1; + int j; + sf_entry *entry; +/* int i already above */ + sf_entry tmp; + int entries; + unsigned a, b; + + /* declarations from GenerateTrees */ + int codelen, lvlstart, next, parents; +/* int i, j already above */ + + /* for Compactor */ + int tree_count[32]; + /* end declarations */ + + /* next paraphrased from ReadLengths with adaption for Compactor. */ + treeBytes = *cpt_char++; + if(size < treeBytes * 2) { /* too many entries, something is wrong! */ + (void)fprintf(stderr, "Bytes is: %d, expected: %d\n", treeBytes, + size / 2); +#ifdef SCAN + do_error("macunpack: error in coding tree"); +#endif /* SCAN */ + exit(1); + } + for(i = 0; i < 32; i++) { + tree_count[i] = 0; + } + i = 0; + tree_MaxLength = 0; + tree_entries = 0; + while(treeBytes-- > 0) { /* adaption for Compactor */ + len = (*cpt_char) >> 4; + if(len != 0) { /* only if length unequal zero */ + if(len > tree_MaxLength) { + tree_MaxLength = len; + } + tree_count[len]++; + tree_entry[tree_entries].Value = i; + tree_entry[tree_entries++].BitLength = len; + } + i++; + len = *cpt_char++ & NIBBLEMASK; + if(len != 0) { /* only if length unequal zero */ + if(len > tree_MaxLength) { + tree_MaxLength = len; + } + tree_count[len]++; + tree_entry[tree_entries].Value = i; + tree_entry[tree_entries++].BitLength = len; + } + i++; + } + + /* Compactor allows unused trailing codes in its Huffman tree! */ + j = 0; + for(i = 0; i <= tree_MaxLength; i++) { + j = (j << 1) + tree_count[i]; + } + j = (1 < 0) && ((a = (ejm1 = &(entry[j - 1]))->BitLength) >= b)) { + if((a == b) && (ejm1->Value <= tmp.Value)) { + break; + } + *(ejm1 + 1) = *ejm1; + --j; + } + entry[j] = tmp; + } + + /* Adapted from GenerateTrees */ + i = tree_entries - 1; + /* starting at the upper end (and reversing loop) because of Compactor */ + lvlstart = next = size * 2 + SLACK - 1; + /* slight adaption because of different node format used */ + for(codelen = tree_MaxLength; codelen >= 1; --codelen) { + while((i >= 0) && (tree_entry[i].BitLength == codelen)) { + Hufftree[next].byte = tree_entry[i].Value; + Hufftree[next].flag = 1; + next--; + i--; + } + parents = next; + if(codelen > 1) { + /* reversed loop */ + for(j = lvlstart; j > parents + 1; j-= 2) { + Hufftree[next].one = &(Hufftree[j]); + Hufftree[next].zero = &(Hufftree[j - 1]); + Hufftree[next].flag = 0; + next--; + } + } + lvlstart = parents; + } + Hufftree[0].one = &(Hufftree[next + 2]); + Hufftree[0].zero = &(Hufftree[next + 1]); + Hufftree[0].flag = 0; +} + +static int cpt_get6bits() +{ +int b = 0, cn; + + b = (cpt_newbits >> 26) & 0x3f; + cpt_bitsavail -= 6; + cpt_newbits <<= 6; + if(cpt_bitsavail < 16) { + cn = (*cpt_char++ << 8); + cn |= *cpt_char++; + cpt_newbits |= (cn << (16 - cpt_bitsavail)); + cpt_bitsavail += 16; + } + return b; +} + +static int cpt_getbit() +{ +int b; + + b = (cpt_newbits >> 31) & 1; + cpt_bitsavail--; + if(cpt_bitsavail < 16) { + cpt_newbits |= (*cpt_char++ << 8); + cpt_newbits |= *cpt_char++; + cpt_bitsavail += 16; + } + cpt_newbits <<= 1; + return b; +} +#else /* CPT */ +int cpt; /* keep lint and some compilers happy */ +#endif /* CPT */ + diff --git a/macunpack/cpt.h b/macunpack/cpt.h new file mode 100755 index 0000000..43700b8 --- /dev/null +++ b/macunpack/cpt.h @@ -0,0 +1,93 @@ +#define C_SIGNATURE 0 +#define C_VOLUME 1 +#define C_XMAGIC 2 +#define C_IOFFSET 4 +#define CPTHDRSIZE 8 + +#define C_HDRCRC 0 +#define C_ENTRIES 4 +#define C_COMMENT 6 +#define CPTHDR2SIZE 7 + +#define CHDRSIZE (CPTHDRSIZE+CPTHDR2SIZE) + +#define F_FNAME 0 +#define F_FOLDER 32 +#define F_FOLDERSIZE 33 +#define F_VOLUME 35 +#define F_FILEPOS 36 +#define F_FTYPE 40 +#define F_CREATOR 44 +#define F_CREATIONDATE 48 +#define F_MODDATE 52 +#define F_FNDRFLAGS 56 +#define F_FILECRC 58 +#define F_CPTFLAG 62 +#define F_RSRCLENGTH 64 +#define F_DATALENGTH 68 +#define F_COMPRLENGTH 72 +#define F_COMPDLENGTH 76 +#define FILEHDRSIZE 80 + +typedef long OSType; + +typedef struct cptHdr { /* 8 bytes */ + unsigned char signature; /* = 1 -- for verification */ + unsigned char volume; /* for multi-file archives */ + unsigned short xmagic; /* verification multi-file consistency*/ + unsigned long offset; /* index offset */ +/* The following are really in header2 at offset */ + unsigned long hdrcrc; /* header crc */ + unsigned short entries; /* number of index entries */ + unsigned char commentsize; /* number of bytes comment that follow*/ +}; + +typedef struct fileHdr { /* 78 bytes */ + unsigned char fName[32]; /* a STR32 */ + unsigned char folder; /* set to 1 if a folder */ + unsigned short foldersize; /* number of entries in folder */ + unsigned char volume; /* for multi-file archives */ + unsigned long filepos; /* position of data in file */ + OSType fType; /* file type */ + OSType fCreator; /* er... */ + unsigned long creationDate; + unsigned long modDate; /* !restored-compat w/backup prgms */ + unsigned short FndrFlags; /* copy of Finder flags. For our + purposes, we can clear: + busy,onDesk */ + unsigned long fileCRC; /* crc on file */ + unsigned short cptFlag; /* cpt flags */ + unsigned long rsrcLength; /* decompressed lengths */ + unsigned long dataLength; + unsigned long compRLength; /* compressed lengths */ + unsigned long compDLength; +}; + + +/* file format is: + cptArchiveHdr + file1data + file1RsrcFork + file1DataFork + file2data + file2RsrcFork + file2DataFork + . + . + . + fileNdata + fileNRsrcFork + fileNDataFork + cptIndex +*/ + + + +/* cpt flags */ +#define encryp 1 /* file is encrypted */ +#define crsrc 2 /* resource fork is compressed */ +#define cdata 4 /* data fork is compressed */ +/* ???? 8 /* unknown */ + +#define CIRCSIZE 8192 + diff --git a/macunpack/cpt.o b/macunpack/cpt.o new file mode 100644 index 0000000..4268419 Binary files /dev/null and b/macunpack/cpt.o differ diff --git a/macunpack/crc.c b/macunpack/crc.c new file mode 100755 index 0000000..0e0baf3 --- /dev/null +++ b/macunpack/crc.c @@ -0,0 +1,4 @@ +unsigned long crcinit; + +unsigned long (*updcrc)(); + diff --git a/macunpack/crc.h b/macunpack/crc.h new file mode 100755 index 0000000..b339d36 --- /dev/null +++ b/macunpack/crc.h @@ -0,0 +1,13 @@ +#define INIT_CRC crcinit + +extern unsigned long arc_crcinit; +extern unsigned long binhex_crcinit; +extern unsigned long zip_crcinit; + +extern unsigned long arc_updcrc(); +extern unsigned long binhex_updcrc(); +extern unsigned long zip_updcrc(); + +extern unsigned long crcinit; +extern unsigned long (*updcrc)(); + diff --git a/macunpack/dd.c b/macunpack/dd.c new file mode 100755 index 0000000..28f417d --- /dev/null +++ b/macunpack/dd.c @@ -0,0 +1,1042 @@ +#include "macunpack.h" +#ifdef DD +#include "globals.h" +#include "dd.h" +#include "crc.h" +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "../fileio/fileglob.h" +#include "../util/masks.h" +#include "../util/util.h" + +extern char *malloc(); +extern char *realloc(); +extern char *strcpy(); +extern char *strncpy(); +extern void cpt_wrfile1(); +extern void core_compress(); +extern void de_compress(); + +static void dd_name(); +static int dd_filehdr(); +static void dd_cfilehdr(); +static int dd_valid(); +static int dd_valid1(); +static char *dd_methname(); +static unsigned long dd_checksum(); +static void dd_chksum(); +static unsigned long dd_checkor(); +static void dd_do_delta(); +static void dd_delta(); +static void dd_delta3(); +static void dd_copy(); +static void dd_copyfile(); +static void dd_expand(); +static void dd_expandfile(); +static void dd_nocomp(); +static void dd_lzc(); +#ifdef UNTESTED +static void dd_rle(); +#ifdef NOTIMPLEMENTED +static void dd_huffman(); +#endif /* NOTIMPLEMENTED */ +static void dd_lzss(); +static int dd_getbits(); +#endif /* UNTESTED */ +static void dd_cpt_compat(); + +typedef struct methodinfo { + char *name; + int number; +}; + +static struct methodinfo methods[] = { + {"NoComp", nocomp}, + {"LZC", lzc}, + {"???", method2}, + {"RLE", rle}, + {"Huffman", huffman}, + {"???", method5}, + {"???", method6}, + {"LZSS", lzss}, + {"RLE/LZH", cpt_compat}, + {"???", method9}, +}; +static unsigned char *dd_archive; +static unsigned char *dd_data_ptr; +static int dd_archive_size; +static int dd_max_archive_size; +static unsigned char *dd_dirst; +static int dd_dirstptr; +static int dd_dirstmax; +static int dd_xor; +static long dd_bitbuf; +static int dd_bitcount; +static unsigned char *dd_bitptr; +static char dd_LZbuff[2048]; + +void dd_file(bin_hdr) +unsigned char *bin_hdr; +{ + unsigned long data_size; + int i; + struct fileCHdr cf; + char ftype[5], fauth[5]; + + updcrc = binhex_updcrc; + crcinit = binhex_crcinit; + dd_name(bin_hdr); + for(i = 0; i < INFOBYTES; i++) { + info[i] = bin_hdr[i]; + } + transname(info + I_NAMEOFF + 1, text, (int)info[I_NAMEOFF] & BYTEMASK); + data_size = get4(info + I_DLENOFF); + if(data_size > dd_max_archive_size) { + if(dd_max_archive_size == 0) { + dd_archive = (unsigned char *)malloc((unsigned)data_size); + } else { + dd_archive = (unsigned char *)realloc((char *)dd_archive, + (unsigned)data_size); + } + dd_max_archive_size = data_size; + if(dd_archive == NULL) { + (void)fprintf(stderr, "Insufficient memory.\n"); + exit(1); + } + } + dd_archive_size = data_size; + if(fread((char *)dd_archive, 1, (int)data_size, infp) != data_size) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("Premature EOF"); +#endif /* SCAN */ + exit(1); + } + dd_data_ptr = dd_archive; + dd_cfilehdr(&cf); + write_it = 1; + if(list) { + do_indent(indent); + transname(info + I_TYPEOFF, ftype, 4); + transname(info + I_AUTHOFF, fauth, 4); + (void)fprintf(stderr, + "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld", + text, ftype, fauth, + (long)get4(info + I_DLENOFF), (long)get4(info + I_RLENOFF)); + if(info_only) { + write_it = 0; + } + if(query) { + write_it = do_query(); + } else { + (void)fputc('\n', stderr); + } + } + if(!dd_valid((int)cf.datamethod, (int)cf.rsrcmethod)) { + (void)fprintf(stderr, "\tUnimplemented method found: %d %d\n", + cf.datamethod, cf.rsrcmethod); +#ifdef SCAN + do_error("macunpack: Unimplemented method found"); +#endif /* SCAN */ + return; + } + + if(write_it) { + define_name(text); + } + if(write_it || list) { + dd_expand(cf, dd_data_ptr); + } +} + +void dd_arch(bin_hdr) +unsigned char *bin_hdr; +{ + unsigned long data_size; + unsigned long crc, filecrc; + struct fileHdr f; + struct fileCHdr cf; + char locname[64]; + int i, nlength; + + updcrc = binhex_updcrc; + crcinit = binhex_crcinit; + data_size = get4((char *)bin_hdr + I_DLENOFF); + if(data_size > dd_max_archive_size) { + if(dd_max_archive_size == 0) { + dd_archive = (unsigned char *)malloc((unsigned)data_size); + } else { + dd_archive = (unsigned char *)realloc((char *)dd_archive, + (unsigned)data_size); + } + dd_max_archive_size = data_size; + } + dd_archive_size = data_size; + if(fread((char *)dd_archive, 1, (int)data_size, infp) != data_size) { + (void)fprintf(stderr, "Insufficient memory.\n"); + exit(1); + } + dd_name(bin_hdr); + nlength = bin_hdr[I_NAMEOFF]; + for(i = 0; i < INFOBYTES; i++) { + info[i] = 0; + } + info[I_NAMEOFF] = nlength; + for(i = 1; i <= nlength; i++) { + info[I_NAMEOFF + i] = bin_hdr[I_NAMEOFF + i]; + } + transname(info + I_NAMEOFF + 1, text, nlength); + (void)strcpy(locname, text); + if(list) { + do_indent(indent); + (void)fprintf(stderr, "folder=\"%s\"", text); + if(query) { + if(!do_query()) { + return; + } + } else { + (void)fputc('\n', stderr); + } + indent++; + } + if(!info_only) { + do_mkdir(text, info); + } + + if(strncmp((char *)dd_archive, "DDAR", 4)) { + (void)fprintf(stderr, "Magic archive header error\n"); +#ifdef SCAN + do_error("macunpack: Magic archive header error"); +#endif /* SCAN */ + exit(1); + } + crc = (*updcrc)(crcinit, dd_archive, ARCHHDRSIZE - 2); + filecrc = get2((char *)dd_archive + ARCHHDRCRC); + if(crc != filecrc) { + (void)fprintf(stderr, "Header CRC mismatch: got 0x%02x, need 0x%02x\n", + (int)crc, (int)filecrc); +#ifdef SCAN + do_error("macunpack: Header CRC mismatch"); +#endif /* SCAN */ + exit(1); + } + dd_data_ptr = dd_archive + ARCHHDRSIZE; + while(dd_data_ptr < dd_archive + data_size) { + switch(dd_filehdr(&f, &cf, dir_skip)) { + case DD_FILE: + dd_chksum(f, dd_data_ptr); + dd_expand(cf, dd_data_ptr); + case DD_IVAL: + dd_data_ptr += f.dataLength - CFILEHDRSIZE; + break; + case DD_COPY: + dd_copy(f, dd_data_ptr); + dd_data_ptr += f.dataLength + f.rsrcLength; + break; + case DD_SDIR: + if(write_it || info_only) { + if(write_it) { + do_mkdir(text, info); + } + if(dd_dirstptr == dd_dirstmax) { + if(dd_dirstmax == 0) { + dd_dirst = (unsigned char *)malloc(64); + } else { + dd_dirst = (unsigned char *)realloc((char *)dd_dirst, + (unsigned)dd_dirstmax + 64); + } + dd_dirstmax += 64; + } + for(i = 0; i < 64; i++) { + dd_dirst[dd_dirstptr + i] = text[i]; + } + dd_dirst += 64; + indent++; + } else { + dir_skip++; + } + break; + case DD_EDIR: + if(dir_skip) { + dir_skip--; + } else { + dd_dirst -= 64; + indent--; + if(list) { + do_indent(indent); + (void)fprintf(stderr, "leaving folder \"%s\"\n", + dd_dirst + dd_dirstptr); + } + if(!info_only) { + enddir(); + } + } + } + } + if(!info_only) { + enddir(); + } + if(list) { + indent--; + do_indent(indent); + (void)fprintf(stderr, "leaving folder \"%s\"\n", locname); + } +} + +static void dd_name(bin_hdr) +unsigned char *bin_hdr; +{ + int nlength; + unsigned char *extptr; + + nlength = bin_hdr[I_NAMEOFF] & BYTEMASK; + extptr = bin_hdr + I_NAMEOFF + nlength - 3; + if(!strncmp((char *)extptr, ".sea", 4) || + !strncmp((char *)extptr, ".Sea", 4) || + !strncmp((char *)extptr, ".SEA", 4)) { + nlength -= 4; + extptr[0] = 0; + extptr[1] = 0; + extptr[2] = 0; + extptr[3] = 0; + bin_hdr[I_NAMEOFF] = nlength; + return; + } + extptr++; + if(!strncmp((char *)extptr, ".dd", 3)) { + nlength -=3; + extptr[0] = 0; + extptr[1] = 0; + extptr[2] = 0; + bin_hdr[I_NAMEOFF] = nlength; + return; + } + if(nlength < 31) { + nlength++; + } + bin_hdr[I_NAMEOFF + nlength] = 0xA5; + bin_hdr[I_NAMEOFF] = nlength; +} + +static int dd_filehdr(f, cf, skip) +struct fileHdr *f; +struct fileCHdr *cf; +int skip; +{ + register int i; + unsigned long crc; + int n, to_uncompress; + unsigned char *hdr; + char ftype[5], fauth[5]; + unsigned long datalength, rsrclength; + + to_uncompress = DD_COPY; + hdr = dd_data_ptr; + dd_data_ptr += FILEHDRSIZE; + for(i = 0; i < INFOBYTES; i++) { + info[i] = '\0'; + } + crc = INIT_CRC; + crc = (*updcrc)(crc, hdr, FILEHDRSIZE - 2); + + f->hdrcrc = get2((char *)hdr + D_HDRCRC); + if(f->hdrcrc != crc) { + (void)fprintf(stderr, "Header CRC mismatch: got 0x%04x, need 0x%04x\n", + f->hdrcrc & WORDMASK, (int)crc); +#ifdef SCAN + do_error("macunpack: Header CRC mismatch"); +#endif /* SCAN */ + exit(1); + } + + n = hdr[D_FNAME] & BYTEMASK; + if(n > F_NAMELEN) { + n = F_NAMELEN; + } + info[I_NAMEOFF] = n; + copy(info + I_NAMEOFF + 1, (char *)hdr + D_FNAME + 1, n); + transname((char *)hdr + D_FNAME + 1, text, n); + + if(!hdr[D_ISDIR]) { + f->datacrc = get2((char *)hdr + D_DATACRC); + f->rsrccrc = get2((char *)hdr + D_RSRCCRC); + f->dataLength = get4((char *)hdr + D_DATALENGTH); + f->rsrcLength = get4((char *)hdr + D_RSRCLENGTH); + copy(info + I_DLENOFF, (char *)hdr + D_DATALENGTH, 4); + copy(info + I_RLENOFF, (char *)hdr + D_RSRCLENGTH, 4); + copy(info + I_CTIMOFF, (char *)hdr + D_CTIME, 4); + copy(info + I_MTIMOFF, (char *)hdr + D_MTIME, 4); + copy(info + I_TYPEOFF, (char *)hdr + D_FTYPE, 4); + copy(info + I_AUTHOFF, (char *)hdr + D_CREATOR, 4); + copy(info + I_FLAGOFF, (char *)hdr + D_FNDRFLAGS, 2); + } + + if(hdr[D_ISDIR]) { + to_uncompress = DD_SDIR; + } else if(hdr[D_ENDDIR]) { + to_uncompress = DD_EDIR; + } else if(!no_dd && ((hdr[D_FNDRFLAGS] & 0x80) == 0)) { + dd_cfilehdr(cf); + to_uncompress = DD_FILE; + datalength = cf->dataLength; + rsrclength = cf->rsrcLength; + } else { + datalength = f->dataLength; + rsrclength = f->rsrcLength; + } + hdr[D_FNDRFLAGS] &= 0x7f; + write_it = !skip; + if(list && !skip) { + if(to_uncompress != DD_EDIR) { + do_indent(indent); + } + if(to_uncompress == DD_SDIR) { + (void)fprintf(stderr, "folder=\"%s\"", text); + } else if(to_uncompress != DD_EDIR) { + transname(info + I_TYPEOFF, ftype, 4); + transname(info + I_AUTHOFF, fauth, 4); + (void)fprintf(stderr, + "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld", + text, ftype, fauth, (long)datalength, (long)rsrclength); + } + if(info_only) { + write_it = 0; + } + if(to_uncompress != DD_EDIR) { + if(query) { + write_it = do_query(); + } else { + (void)fputc('\n', stderr); + } + } + if(to_uncompress == DD_FILE) { + if(!dd_valid((int)cf->datamethod, (int)cf->rsrcmethod)) { + (void)fprintf(stderr, "\tUnimplemented method found: %d %d\n", + cf->datamethod, cf->rsrcmethod); +#ifdef SCAN + do_error("macunpack: Unimplemented method found"); +#endif /* SCAN */ + return DD_IVAL; + } + } + } + + if(write_it) { + define_name(text); + } + return to_uncompress; +} + +static void dd_cfilehdr(f) +struct fileCHdr *f; +{ + unsigned long crc; + unsigned char *hdr; + + hdr = dd_data_ptr; + dd_data_ptr += CFILEHDRSIZE; + crc = INIT_CRC; + crc = (*updcrc)(crc, hdr, CFILEHDRSIZE - 2); + + f->hdrcrc = get2((char *)hdr + C_HDRCRC); + if(f->hdrcrc != crc) { + (void)fprintf(stderr, "Header CRC mismatch: got 0x%04x, need 0x%04x\n", + f->hdrcrc & WORDMASK, (int)crc); +#ifdef SCAN + do_error("macunpack: Header CRC mismatch"); +#endif /* SCAN */ + exit(1); + } + + f->dataLength = get4((char *)hdr + C_DATALENGTH); + f->dataCLength = get4((char *)hdr + C_DATACLENGTH); + f->rsrcLength = get4((char *)hdr + C_RSRCLENGTH); + f->rsrcCLength = get4((char *)hdr + C_RSRCCLENGTH); + f->datamethod = hdr[C_DATAMETHOD]; + f->rsrcmethod = hdr[C_RSRCMETHOD]; + f->datacrc = get2((char *)hdr + C_DATACRC); + f->rsrccrc = get2((char *)hdr + C_RSRCCRC); + f->datainfo = get2((char *)hdr + C_DATAINFO); + f->rsrcinfo = get2((char *)hdr + C_RSRCINFO); + f->datacrc2 = get2((char *)hdr + C_DATACRC2); + f->rsrccrc2 = get2((char *)hdr + C_RSRCCRC2); + f->info1 = hdr[C_INFO1]; + f->info2 = hdr[C_INFO2]; + copy(info + I_DLENOFF, (char *)hdr + C_DATALENGTH, 4); + copy(info + I_RLENOFF, (char *)hdr + C_RSRCLENGTH, 4); + copy(info + I_CTIMOFF, (char *)hdr + C_CTIME, 4); + copy(info + I_MTIMOFF, (char *)hdr + C_MTIME, 4); + copy(info + I_TYPEOFF, (char *)hdr + C_FTYPE, 4); + copy(info + I_AUTHOFF, (char *)hdr + C_CREATOR, 4); + copy(info + I_FLAGOFF, (char *)hdr + C_FNDRFLAGS, 2); + if(f->info1 >= 0x2a && (f->info2 & 0x80) == 0) { + dd_xor = 0x5a; + } else { + dd_xor = 0; + } +} + +static int dd_valid(dmethod, rmethod) +int dmethod, rmethod; +{ + return dd_valid1(dmethod) | dd_valid1(rmethod); +} + +static int dd_valid1(method) +int method; +{ + switch(method) { + case nocomp: + case lzc: +#ifdef UNTESTED + case rle: +#ifdef NOTIMPLEMENTED + case huffman: +#endif /* NOTIMPLEMENTED */ + case lzss: +#endif /* UNTESTED */ + case cpt_compat: + return 1; + } + return 0; +} + +static char *dd_methname(n) +int n; +{ +int i, nmeths; + nmeths = sizeof(methods) / sizeof(struct methodinfo); + for(i = 0; i < nmeths; i++) { + if(methods[i].number == n) { + return methods[i].name; + } + } + return NULL; +} + +static unsigned long dd_checksum(init, buffer, length) +unsigned long init; +char *buffer; +unsigned long length; +{ + int i; + unsigned long cks; + + cks = init; + for(i = 0; i < length; i++) { + cks += *buffer++ & BYTEMASK; + } + return cks & WORDMASK; +} + +static void dd_chksum(hdr, data) +struct fileHdr hdr; +unsigned char *data; +{ + unsigned long cks; + + if(write_it) { + cks = dd_checksum(INIT_CRC, (char *)data - CFILEHDRSIZE, + hdr.dataLength); + if(hdr.datacrc != cks) { + (void)fprintf(stderr, + "Checksum error on compressed file: need 0x%04x, got 0x%04x\n", + hdr.datacrc, (int)cks); +#ifdef SCAN + do_error("macunpack: Checksum error on compressed file"); +#endif /* SCAN */ + exit(1); + } + } +} + +static unsigned long dd_checkor(init, buffer, length) +unsigned long init; +char *buffer; +unsigned long length; +{ + int i; + unsigned long cks; + + cks = init; + for(i = 0; i < length; i++) { + cks ^= *buffer++ & BYTEMASK; + } + return cks & WORDMASK; +} + +static void dd_do_delta(out_ptr, nbytes, kind) +char *out_ptr; +unsigned long nbytes; +int kind; +{ + switch(kind) { + case 0: + break; + case 1: + dd_delta(out_ptr, nbytes); + break; + case 2: + dd_delta3(out_ptr, nbytes); + break; + default: + (void)fprintf(stderr, "Illegal kind value found: %d\n", kind); +#ifdef SCAN + do_error("Illegal kind value found"); +#endif /* SCAN */ + exit(1); + } +} + +static void dd_delta(out_ptr, nbytes) +char *out_ptr; +unsigned long nbytes; +{ + int i, sum = 0; + + for(i = 0; i < nbytes; i++) { + sum = (sum + *out_ptr) & BYTEMASK; + *out_ptr++ = sum; + } +} + +static void dd_delta3(out_ptr, nbytes) +char *out_ptr; +unsigned long nbytes; +{ + int i, sum1 = 0, sum2 = 0, sum3 = 0; + + for(i = 0; i < nbytes; i += 3) { + sum1 = (sum1 + *out_ptr) & BYTEMASK; + *out_ptr++ = sum1; + if(i < nbytes - 1) { + sum2 = (sum2 + *out_ptr) & BYTEMASK; + *out_ptr++ = sum2; + if(i < nbytes) { + sum3 = (sum3 + *out_ptr) & BYTEMASK; + *out_ptr++ = sum3; + } + } + } +} + +/*---------------------------------------------------------------------------*/ +/* Archive only, no compression */ +/*---------------------------------------------------------------------------*/ +static void dd_copy(hdr, data) +struct fileHdr hdr; +unsigned char *data; +{ + unsigned long cks; + + if(write_it) { + start_info(info, hdr.rsrcLength, hdr.dataLength); + } + if(verbose) { + (void)fprintf(stderr, "\tNo compression"); + } + if(write_it) { + start_data(); + } + dd_copyfile(hdr.dataLength, data); + data += hdr.dataLength; + if(write_it) { + cks = dd_checksum(INIT_CRC, out_buffer, hdr.dataLength); + if(hdr.datacrc != cks) { + (void)fprintf(stderr, + "Checksum error on data fork: need 0x%04x, got 0x%04x\n", + hdr.datacrc, (int)cks); +#ifdef SCAN + do_error("macunpack: Checksum error on data fork"); +#endif /* SCAN */ + exit(1); + } + } + if(write_it) { + start_rsrc(); + } + dd_copyfile(hdr.rsrcLength, data); + data += hdr.rsrcLength; + if(write_it) { + cks = dd_checksum(INIT_CRC, out_buffer, hdr.rsrcLength); + if(hdr.rsrccrc != cks) { + (void)fprintf(stderr, + "Checksum error on resource fork: need 0x%04x, got 0x%04x\n", + hdr.rsrccrc, (int)cks); +#ifdef SCAN + do_error("macunpack: Checksum error on resource fork"); +#endif /* SCAN */ + exit(1); + } + end_file(); + } + if(verbose) { + (void)fprintf(stderr, ".\n"); + } +} + +static void dd_copyfile(obytes, data) +unsigned long obytes; +unsigned char *data; +{ + if(obytes == 0) { + return; + } + if(write_it) { + copy(out_ptr, (char *)data, (int)obytes); + } +} + +/*---------------------------------------------------------------------------*/ +/* Possible compression, and perhaps in an archive */ +/*---------------------------------------------------------------------------*/ +static void dd_expand(hdr, data) +struct fileCHdr hdr; +unsigned char *data; +{ + unsigned long cks; + char *out_buf; + + if(write_it) { + start_info(info, hdr.rsrcLength, hdr.dataLength); + } + if(verbose) { + (void)fprintf(stderr, "\tData: "); + } + if(write_it) { + start_data(); + } + out_buf = out_buffer; + dd_expandfile(hdr.dataLength, hdr.dataCLength, (int)hdr.datamethod, + (int)hdr.datainfo, data, (unsigned long)hdr.datacrc); + data += hdr.dataCLength; + if(write_it) { + if((hdr.info2 & 0x40) && (hdr.dataLength != 0)) { + cks = arc_updcrc(INIT_CRC, (unsigned char *)out_buf, + (int)hdr.dataLength); + if(cks != hdr.datacrc2) { + (void)fprintf(stderr, + "Checksum error on data fork: need 0x%04x, got 0x%04x\n", + (int)hdr.datacrc2, (int)cks); +#ifdef SCAN + do_error("macunpack: Checksum error on data fork"); +#endif /* SCAN */ + exit(1); + } + } + } + if(verbose) { + (void)fprintf(stderr, ", Rsrc: "); + } + if(write_it) { + start_rsrc(); + } + out_buf = out_buffer; + dd_expandfile(hdr.rsrcLength, hdr.rsrcCLength, (int)hdr.rsrcmethod, + (int)hdr.rsrcinfo, data, (unsigned long)hdr.rsrccrc); + data += hdr.rsrcCLength; + if(write_it) { + if((hdr.info2 & 0x40) && (hdr.rsrcLength != 0)) { + cks = arc_updcrc(INIT_CRC, (unsigned char *)out_buf, + (int)hdr.rsrcLength); + if(cks != hdr.rsrccrc2) { + (void)fprintf(stderr, + "Checksum error on resource fork: need 0x%04x, got 0x%04x\n", + (int)hdr.rsrccrc2, (int)cks); +#ifdef SCAN + do_error("macunpack: Checksum error on resource fork"); +#endif /* SCAN */ + exit(1); + } + } + end_file(); + } + if(verbose) { + (void)fprintf(stderr, ".\n"); + } +} + +static void dd_expandfile(obytes, ibytes, method, kind, data, chksum) +unsigned long obytes, ibytes, chksum; +int method, kind; +unsigned char *data; +{ + int sub_method, m1, m2; + char *optr = out_ptr; + unsigned long cksinit; + + if(obytes == 0) { + if(verbose) { + (void)fprintf(stderr, "empty"); + } + return; + } + switch(method & 0x7f) { + case nocomp: + if(verbose) { + (void)fprintf(stderr, "No compression"); + } + if(write_it) { + dd_nocomp(obytes, data); + } + break; + case lzc: + m1 = (*data++ & BYTEMASK) ^ dd_xor; + m2 = (*data++ & BYTEMASK) ^ dd_xor; + sub_method = (*data++ & BYTEMASK) ^ dd_xor; + cksinit = m1 + m2 + sub_method; + sub_method = sub_method & 0x1f; + if(verbose) { + (void)fprintf(stderr, "LZC(%d) compressed (%4.1f%%)", + sub_method, 100.0 * ibytes / obytes); + } + if(write_it) { + dd_lzc(ibytes - 3, obytes, data, sub_method, chksum, cksinit); + } + break; +#ifdef UNTESTED + case rle: + if(verbose) { + (void)fprintf(stderr, "RLE compressed (%4.1f%%)", + 100.0 * ibytes / obytes); + } + if(write_it) { + dd_rle(ibytes, data); + } + break; +#ifdef NOTIMPLEMENTED + case huffman: + if(verbose) { + (void)fprintf(stderr, "Huffman compressed (%4.1f%%)", + 100.0 * ibytes / obytes); + } + if(write_it) { + dd_huffman(ibytes, data); + } + break; +#endif /* NOTIMPLEMENTED */ + case lzss: + if(verbose) { + (void)fprintf(stderr, "LZSS compressed (%4.1f%%)", + 100.0 * ibytes / obytes); + } + if(write_it) { + dd_lzss(data, chksum); + } + break; +#endif /* UNTESTED */ + case cpt_compat: + sub_method = get2((char *)data); + data += 16; + if(sub_method != 0) { + sub_method = 0; + } else { + sub_method = 1; + } + if(verbose) { + if(!sub_method) { + (void)fprintf(stderr, "RLE compressed (%4.1f%%)", + 100.0 * ibytes / obytes); + } else { + (void)fprintf(stderr, "RLE/LZH compressed (%4.1f%%)", + 100.0 * ibytes / obytes); + } + } + if(write_it) { + dd_cpt_compat(ibytes, obytes, data, sub_method, chksum); + } + break; + default: + break; + } + if(write_it) { + dd_do_delta(optr, obytes, kind); + } +} + +/*---------------------------------------------------------------------------*/ +/* Method 0: no compression */ +/*---------------------------------------------------------------------------*/ +static void dd_nocomp(obytes, data) +unsigned char *data; +unsigned long obytes; +{ + copy(out_ptr, (char *)data, (int)obytes); +} + +/*---------------------------------------------------------------------------*/ +/* Method 1: LZC compressed */ +/*---------------------------------------------------------------------------*/ +static void dd_lzc(ibytes, obytes, data, mb, chksum, ckinit) +unsigned char *data; +unsigned long ibytes, obytes, chksum, ckinit; +int mb; +{ + int i; + char *out_buf; + unsigned long cks; + + out_buf = out_buffer; + core_compress((char *)data); + de_compress(ibytes, mb); + out_buffer = out_buf; + if(dd_xor != 0) { + for(i = 0; i < obytes; i++) { + *out_buf++ ^= dd_xor; + } + } + cks = dd_checksum(ckinit, out_buffer, obytes); + if(chksum != cks) { + (void)fprintf(stderr, + "Checksum error on fork: need 0x%04x, got 0x%04x\n", + (int)chksum, (int)cks); +#ifdef SCAN + do_error("macunpack: Checksum error on fork"); +#endif /* SCAN */ + exit(1); + } +} + +#ifdef UNTESTED +/*---------------------------------------------------------------------------*/ +/* Method 3: Run length encoding */ +/*---------------------------------------------------------------------------*/ +static void dd_rle(ibytes, data) +unsigned char *data; +unsigned long ibytes; +{ + int ch, lastch, n, i; + + while(ibytes != 0) { + ch = *data++; + ibytes--; + if(ch == ESC) { + n = *data++ - 1; + ibytes--; + if(n < 0) { + *out_ptr++ = ESC; + lastch = ESC; + } else { + for(i = 0; i < n; i++) { + *out_ptr++ = lastch; + } + } + } else { + *out_ptr++ = ch; + lastch = ch; + } + } +} + +#ifdef NOTIMPLEMENTED +/*---------------------------------------------------------------------------*/ +/* Method 4: Huffman encoding */ +/*---------------------------------------------------------------------------*/ +static void dd_huffman(ibytes, data) +unsigned char *data; +unsigned long ibytes; +{ +} +#endif /* NOTIMPLEMENTED */ + +/*---------------------------------------------------------------------------*/ +/* Method 7: Slightly improved LZSS */ +/*---------------------------------------------------------------------------*/ +static void dd_lzss(data, chksum) +unsigned char *data; +unsigned long chksum; +{ + int i, LZptr, LZbptr, LZlength; + char *optr = out_ptr; + unsigned char cks; + + data += get4((char *)data + 6); + LZptr = 0; + while(1) { + if(dd_getbits(1) == 0) { + *out_ptr++ = dd_LZbuff[LZptr++] = dd_getbits(8); + LZptr &= 0x7ff; + } else { + if(dd_getbits(1) == 0) { + LZbptr = dd_getbits(11); + } else { + LZbptr = dd_getbits(7); + } + if(LZbptr == 0) { + break; + } + LZbptr = (LZptr - LZbptr) & 0x7ff; + LZlength = dd_getbits(2); + if(LZlength == 3) { + LZlength += dd_getbits(2); + if(LZlength == 6) { + do { + i = dd_getbits(4); + LZlength += i; + } while(i == 15); + } + } + LZlength += 2; + for(i = 0; i < LZlength; i++) { + *out_ptr++ = dd_LZbuff[LZptr++] = dd_LZbuff[LZbptr++]; + LZptr &= 0x7ff; + LZbptr &= 0x7ff; + } + } + } + cks = dd_checkor(INIT_CRC, optr, (unsigned long)(out_ptr - optr)); + if(chksum != cks) { + (void)fprintf(stderr, + "Checksum error on fork: need 0x%04x, got 0x%04x\n", + (int)chksum, (int)cks); +#ifdef SCAN + do_error("macunpack: Checksum error on fork"); +#endif /* SCAN */ + exit(1); + } +} + +static int dd_getbits(n) +int n; +{ + int r; + + while(dd_bitcount < n) { + dd_bitbuf = (dd_bitbuf << 8) | (~(*dd_bitptr++) & BYTEMASK); + dd_bitcount += 8; + } + dd_bitcount -= n; + r = (dd_bitbuf >> dd_bitcount); + dd_bitbuf ^= (r << dd_bitcount); + return r; +} + +#endif /* UNTESTED */ + +/*---------------------------------------------------------------------------*/ +/* Method 8: Compactor compatible compression */ +/*---------------------------------------------------------------------------*/ +static void dd_cpt_compat(ibytes, obytes, data, sub_method, chksum) +unsigned char *data; +unsigned long ibytes, obytes, chksum; +int sub_method; +{ + unsigned long cks; + char *optr = out_buffer; + + cpt_wrfile1(data, ibytes, obytes, sub_method, (unsigned long)0x0fff0); + cks = arc_updcrc(INIT_CRC, (unsigned char *)optr, (int)obytes); + if(chksum != cks) { + (void)fprintf(stderr, + "Checksum error on fork: need 0x%04x, got 0x%04x\n", + (int)chksum, (int)cks); +#ifdef SCAN + do_error("macunpack: Checksum error on fork"); +#endif /* SCAN */ + exit(1); + } +} +#else /* DD */ +int dd; /* keep lint and some compilers happy */ +#endif /* DD */ + diff --git a/macunpack/dd.h b/macunpack/dd.h new file mode 100755 index 0000000..1fc0453 --- /dev/null +++ b/macunpack/dd.h @@ -0,0 +1,125 @@ +#define MAGIC1 "DDAR" +#define MAGIC2 "\253\315\000\124" + +/* Initial header */ +#define ARCHHDRCRC 76 +#define ARCHHDRSIZE 78 + +/* File headers */ +#define D_MAGIC 0 +#define D_FILL1 4 +#define D_FNAME 8 +#define D_ISDIR 72 +#define D_ENDDIR 73 +#define D_DATALENGTH 74 +#define D_RSRCLENGTH 78 +#define D_CTIME 82 +#define D_MTIME 86 +#define D_FTYPE 90 +#define D_CREATOR 94 +#define D_FNDRFLAGS 98 +#define D_FILL2 100 +#define D_DATACRC 118 +#define D_RSRCCRC 120 +#define D_HDRCRC 122 +#define FILEHDRSIZE 124 + +/* Compressed file header */ +#define C_MAGIC 0 +#define C_DATALENGTH 4 +#define C_DATACLENGTH 8 +#define C_RSRCLENGTH 12 +#define C_RSRCCLENGTH 16 +#define C_DATAMETHOD 20 +#define C_RSRCMETHOD 21 +#define C_INFO1 22 +#define C_MTIME 24 +#define C_CTIME 28 +#define C_FTYPE 32 +#define C_CREATOR 36 +#define C_FNDRFLAGS 40 +#define C_FILL1 42 +#define C_DATACRC 48 +#define C_RSRCCRC 50 +#define C_INFO2 52 +#define C_DATAINFO 54 +#define C_RSRCINFO 56 +#define C_FILL2 58 +#define C_DATACRC2 78 +#define C_RSRCCRC2 80 +#define C_HDRCRC 82 +#define CFILEHDRSIZE 84 + +typedef long OSType; + +typedef struct fileHdr { /* 124 bytes */ + unsigned char magic[4]; /* "DDAR" */ + unsigned char fill1[4]; /* ??? */ + unsigned char fName[64]; /* a STR63 */ + unsigned char isdir; /* starts a directory? */ + unsigned char enddir; /* terminates a directory? */ + unsigned long dataLength; /* lengths */ + unsigned long rsrcLength; + unsigned long creationDate; + unsigned long modDate; + OSType fType; /* file type */ + OSType fCreator; /* er... */ + unsigned short FndrFlags; /* copy of Finder flags. For our + purposes, we can clear: + busy,onDesk */ + unsigned char fill2[18]; /* ??? */ + unsigned short datacrc; /* checksum */ + unsigned short rsrccrc; + unsigned short hdrcrc; /* true crc */ +}; + +typedef struct fileCHdr { /* 84 bytes */ + unsigned char magic[4]; /* "\253\315\000\124" */ + unsigned long dataLength; /* lengths */ + unsigned long dataCLength; + unsigned long rsrcLength; + unsigned long rsrcCLength; + unsigned char datamethod; /* compression method used */ + unsigned char rsrcmethod; + unsigned char info1; /* flags ??? */ + unsigned char fill3; + unsigned long modDate; + unsigned long creationDate; + OSType fType; /* file type */ + OSType fCreator; /* er... */ + unsigned short FndrFlags; /* copy of Finder flags. For our + purposes, we can clear: + busy,onDesk */ + unsigned char fill1[6]; /* ??? */ + unsigned short datacrc; /* checksum */ + unsigned short rsrccrc; + unsigned char info2; /* flags ??? */ + unsigned char fill4; + unsigned short datainfo; /* ??? */ + unsigned short rsrcinfo; /* ??? */ + unsigned char fill2[20]; /* ??? */ + unsigned short datacrc2; /* other checksum */ + unsigned short rsrccrc2; + unsigned short hdrcrc; /* true crc */ +}; + +#define DD_FILE 0 +#define DD_COPY 1 +#define DD_SDIR 2 +#define DD_EDIR 3 +#define DD_IVAL 4 + +/* Methods used */ +#define nocomp 0 +#define lzc 1 +#define method2 2 +#define rle 3 +#define huffman 4 +#define method5 5 +#define method6 6 +#define lzss 7 +#define cpt_compat 8 +#define method9 9 + +#define ESC 0x144 /* Repeat packing escape */ + diff --git a/macunpack/de_compress.c b/macunpack/de_compress.c new file mode 100755 index 0000000..a393a5a --- /dev/null +++ b/macunpack/de_compress.c @@ -0,0 +1,225 @@ +#include "macunpack.h" +#ifdef SIT +#define DECOMPRESS +#endif /* SIT */ +#ifdef LZC +#define DECOMPRESS +#endif /* LZC */ +#ifdef DECOMPRESS +#include "globals.h" +#include "../fileio/wrfile.h" + +/* Written to allow for bits to be upto 16, MacCompress can use 16 bits */ + +#define BITS 16 +#define HSIZE 69001 /* 95% occupancy */ + +#define INIT_BITS 9 /* initial number of bits/code */ + +static int n_bits; /* number of bits/code */ +static int maxbits; /* user settable max # bits/code */ +static long maxcode; /* maximum code, given n_bits */ +static long maxmaxcode; /* should NEVER generate this code */ +# define MAXCODE(n_bits) ((1 << (n_bits)) - 1) + +static long htab [HSIZE]; +static unsigned short codetab [HSIZE]; + +#define tab_prefixof(i) codetab[i] +#define tab_suffixof(i) ((unsigned char *)(htab))[i] +#define de_stack ((unsigned char *)&tab_suffixof(1<= 0; code--) { + tab_prefixof(code) = 0; + tab_suffixof(code) = (unsigned char)code; + } + free_ent = FIRST; + finchar = oldcode = getcode(); + if(oldcode == -1) { /* EOF already? */ + return; /* Get out of here */ + } + /* first code must be 8 bits = char */ + *out_ptr++ = (char)finchar; + stackp = de_stack; + while((code = getcode()) > -1) { + if(code == CLEAR) { + for(code = 255; code >= 0; code--) { + tab_prefixof(code) = 0; + } + clear_flg = 1; + free_ent = FIRST - 1; + if((code = getcode()) == -1) { /* O, untimely death! */ + break; + } + } + incode = code; + /* + * Special case for KwKwK string. + */ + if(code >= free_ent) { + *stackp++ = finchar; + code = oldcode; + } + /* + * Generate output characters in reverse order + */ + while(code >= 256) { + *stackp++ = tab_suffixof(code); + code = tab_prefixof(code); + } + *stackp++ = finchar = tab_suffixof(code); + /* + * And put them out in forward order + */ + do { + *out_ptr++ = (char)*--stackp; + } while(stackp > de_stack); + /* + * Generate the new entry. + */ + if((code=free_ent) < maxmaxcode) { + tab_prefixof(code) = (unsigned short)oldcode; + tab_suffixof(code) = finchar; + free_ent = code+1; + } + /* + * Remember previous code. + */ + oldcode = incode; + } + return; +} + +static unsigned char rmask[9] = + {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; + +static int get_core_bytes; +static char *core_ptr; +static int file_bytes(); +static int core_bytes(); + +static long getcode() +{ + register long code; + static int offset = 0, size = 0; + static unsigned char buf[BITS]; + register int r_off, bits; + register unsigned char *bp = buf; + + if(clear_flg > 0 || offset >= size || free_ent > maxcode) { + /* + * If the next entry will be too big for the current code + * size, then we must increase the size. This implies reading + * a new buffer full, too. + */ + if(free_ent > maxcode) { + n_bits++; + if(n_bits == maxbits) { + maxcode = maxmaxcode; /* won't get any bigger now */ + } else { + maxcode = MAXCODE(n_bits); + } + } + if(clear_flg > 0) { + maxcode = MAXCODE (n_bits = INIT_BITS); + clear_flg = 0; + } + if(toread == 0) { + return -1; + } + if(get_core_bytes) { + size = core_bytes((char *)buf, (n_bits < toread ? n_bits : toread)); + } else { + size = file_bytes((char *)buf, (n_bits < toread ? n_bits : toread)); + } + toread -= size; + if(size <= 0) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("macunpack: Premature EOF"); +#endif /* SCAN */ + exit(1); + } + offset = 0; + /* Round size down to integral number of codes */ + size = (size << 3) - (n_bits - 1); + } + r_off = offset; + bits = n_bits; + /* + * Get to the first byte. + */ + bp += (r_off >> 3); + r_off &= 7; + /* Get first part (low order bits) */ + code = (*bp++ >> r_off); + bits -= (8 - r_off); + r_off = 8 - r_off; /* now, offset into code word */ + /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ + if(bits >= 8) { + code |= *bp++ << r_off; + r_off += 8; + bits -= 8; + } + /* high order bits. */ + code |= (*bp & rmask[bits]) << r_off; + offset += n_bits; + return code; +} + +static int file_bytes(buf, length) +char *buf; +int length; +{ + return fread(buf, 1, length, infp); +} + +static int core_bytes(buf, length) +char *buf; +int length; +{ + int i; + + for(i = 0; i < length; i++) { + *buf++ = *core_ptr++; + } + return length; +} + +void core_compress(ptr) +char *ptr; +{ + core_ptr = ptr; + get_core_bytes = ptr != NULL; +} +#else /* DECOMPRESS */ +int decompress; /* keep lint and some compilers happy */ +#endif /* DECOMPRESS */ + diff --git a/macunpack/de_huffman.c b/macunpack/de_huffman.c new file mode 100755 index 0000000..860d2fc --- /dev/null +++ b/macunpack/de_huffman.c @@ -0,0 +1,154 @@ +#include "macunpack.h" +#ifdef JDW +#define DEHUFFMAN +#endif /* JDW */ +#ifdef STF +#define DEHUFFMAN +#endif /* STF */ +#ifdef PIT +#define DEHUFFMAN +#endif /* PIT */ +#ifdef SIT +#define DEHUFFMAN +#endif /* SIT */ +#ifdef CPT +#define DEHUFFMAN +#endif /* CPT */ +#ifdef DEHUFFMAN +#include "globals.h" +#include "../util/masks.h" +#include "../fileio/wrfile.h" +#include "huffman.h" +#include "../util/util.h" + +int (*get_bit)(); +int bytesread; +/* 515 because StuffIt Classic needs more than the needed 511 */ +struct node nodelist[515]; +static int getbit_be(); +static int getbit_le(); +static int getdecodebyte(); + +static node *nodeptr, *read_sub_tree(); + +static int bit; + +void de_huffman(obytes) +unsigned long obytes; +{ + while(obytes != 0) { + *out_ptr++ = gethuffbyte(nodelist); + obytes--; + } + return; +} + +void de_huffman_end(term) +unsigned int term; +{ + int c; + + while((c = gethuffbyte(nodelist)) != term) { + *out_ptr++ = c; + } +} + +void set_huffman(endian) +int endian; +{ + if(endian == HUFF_LE) { + get_bit = getbit_le; + } else if(endian == HUFF_BE) { + get_bit = getbit_be; + } +} + +void read_tree() +{ + nodeptr = nodelist; + bit = 0; /* put us on a boundary */ + (void)read_sub_tree(); +} + +/* This routine recursively reads the Huffman encoding table and builds + a decoding tree. */ +static node *read_sub_tree() +{ + node *np; + + np = nodeptr++; + if((*get_bit)() == 1) { + np->flag = 1; + np->byte = getdecodebyte(); + } else { + np->flag = 0; + np->zero = read_sub_tree(); + np->one = read_sub_tree(); + } + return np; +} + +/* This routine returns the next bit in the input stream (MSB first) */ +static int getbit_be() +{ + static int b; + + if(bit == 0) { + b = getb(infp) & BYTEMASK; + bit = 8; + bytesread++; + } + bit--; + return (b >> bit) & 1; +} + +/* This routine returns the next bit in the input stream (LSB first) */ +static int getbit_le() +{ + static int b; + + if(bit == 0) { + b = getb(infp) & BYTEMASK; + bit = 8; + bytesread++; + } + bit--; + return (b >> (7 - bit)) & 1; +} + +void clrhuff() +{ + bit = 0; +} + +int gethuffbyte(l_nodelist) +node *l_nodelist; +{ + register node *np; + + np = l_nodelist; + while(np->flag == 0) { + np = (*get_bit)() ? np->one : np->zero; + } + return np->byte; +} + +int getihuffbyte() +{ + return gethuffbyte(nodelist); +} + +static int getdecodebyte() +{ + register int i, b; + + b = 0; + for(i = 8; i > 0; i--) { + b = (b << 1) + (*get_bit)(); + } + return b; +} +#else /* DEHUFFMAN */ +int dehuffman; /* keep lint and some compilers happy */ +#endif /* DEHUFFMAN */ + diff --git a/macunpack/de_lzah.c b/macunpack/de_lzah.c new file mode 100755 index 0000000..bfa28e7 --- /dev/null +++ b/macunpack/de_lzah.c @@ -0,0 +1,276 @@ +#include "macunpack.h" +#ifdef SIT +#define DELZAH +#endif /* SIT */ +#ifdef LZH +#define DELZAH +#endif /* LZH */ +#ifdef DELZAH +#include "globals.h" +#include "../util/masks.h" +#include "../fileio/wrfile.h" + +/* Note: compare with LZSS decoding in lharc! */ + +#define N 314 +#define T (2*N-1) + +/* Huffman table used for first 6 bits of offset: + #bits codes + 3 0x000 + 4 0x040-0x080 + 5 0x100-0x2c0 + 6 0x300-0x5c0 + 7 0x600-0xbc0 + 8 0xc00-0xfc0 +*/ + +static unsigned short HuffCode[] = { + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x040, 0x040, 0x040, 0x040, 0x040, 0x040, 0x040, 0x040, + 0x040, 0x040, 0x040, 0x040, 0x040, 0x040, 0x040, 0x040, + 0x080, 0x080, 0x080, 0x080, 0x080, 0x080, 0x080, 0x080, + 0x080, 0x080, 0x080, 0x080, 0x080, 0x080, 0x080, 0x080, + 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, + 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, + 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, + 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, + 0x180, 0x180, 0x180, 0x180, 0x180, 0x180, 0x180, 0x180, + 0x1c0, 0x1c0, 0x1c0, 0x1c0, 0x1c0, 0x1c0, 0x1c0, 0x1c0, + 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, + 0x240, 0x240, 0x240, 0x240, 0x240, 0x240, 0x240, 0x240, + 0x280, 0x280, 0x280, 0x280, 0x280, 0x280, 0x280, 0x280, + 0x2c0, 0x2c0, 0x2c0, 0x2c0, 0x2c0, 0x2c0, 0x2c0, 0x2c0, + 0x300, 0x300, 0x300, 0x300, 0x340, 0x340, 0x340, 0x340, + 0x380, 0x380, 0x380, 0x380, 0x3c0, 0x3c0, 0x3c0, 0x3c0, + 0x400, 0x400, 0x400, 0x400, 0x440, 0x440, 0x440, 0x440, + 0x480, 0x480, 0x480, 0x480, 0x4c0, 0x4c0, 0x4c0, 0x4c0, + 0x500, 0x500, 0x500, 0x500, 0x540, 0x540, 0x540, 0x540, + 0x580, 0x580, 0x580, 0x580, 0x5c0, 0x5c0, 0x5c0, 0x5c0, + 0x600, 0x600, 0x640, 0x640, 0x680, 0x680, 0x6c0, 0x6c0, + 0x700, 0x700, 0x740, 0x740, 0x780, 0x780, 0x7c0, 0x7c0, + 0x800, 0x800, 0x840, 0x840, 0x880, 0x880, 0x8c0, 0x8c0, + 0x900, 0x900, 0x940, 0x940, 0x980, 0x980, 0x9c0, 0x9c0, + 0xa00, 0xa00, 0xa40, 0xa40, 0xa80, 0xa80, 0xac0, 0xac0, + 0xb00, 0xb00, 0xb40, 0xb40, 0xb80, 0xb80, 0xbc0, 0xbc0, + 0xc00, 0xc40, 0xc80, 0xcc0, 0xd00, 0xd40, 0xd80, 0xdc0, + 0xe00, 0xe40, 0xe80, 0xec0, 0xf00, 0xf40, 0xf80, 0xfc0}; + +static short HuffLength[] = { + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; + +unsigned char (*lzah_getbyte)(); + +static void lzah_inithuf(); +static void lzah_reorder(); +static void lzah_move(); +static void lzah_getbit(); +static void lzah_outchar(); + +static char lzah_buf[4096]; +static int lzah_bufptr; +static int lzah_bitsavail; +static int lzah_bits; +static int Frequ[1000]; +static int ForwTree[1000]; +static int BackTree[1000]; + +void de_lzah(obytes) +unsigned long obytes; +{ + int i, i1, j, ch, byte, offs, skip; + + lzah_inithuf(); + lzah_bitsavail = 0; + for(i = 0; i < 4036; i++) { + lzah_buf[i] = ' '; + } + lzah_bufptr = 4036; + while(obytes != 0) { + ch = ForwTree[T - 1]; + while(ch < T) { + lzah_getbit(); + if(lzah_bits & 0x80) { + ch = ch + 1; + } + ch = ForwTree[ch]; + } + ch -= T; + if(Frequ[T - 1] >= 0x8000) { + lzah_reorder(); + } + + i = BackTree[ch + T]; + do { + j = ++Frequ[i]; + i1 = i + 1; + if(Frequ[i1] < j) { + while(Frequ[++i1] < j) ; + i1--; + Frequ[i] = Frequ[i1]; + Frequ[i1] = j; + + j = ForwTree[i]; + BackTree[j] = i1; + if(j < T) { + BackTree[j + 1] = i1; + } + ForwTree[i] = ForwTree[i1]; + ForwTree[i1] = j; + j = ForwTree[i]; + BackTree[j] = i; + if(j < T) { + BackTree[j + 1] = i; + } + i = i1; + } + i = BackTree[i]; + } while(i != 0); + + if(ch < 256) { + lzah_outchar((char)ch); + obytes--; + } else { + if(lzah_bitsavail != 0) { + byte = (lzah_bits << 1) & BYTEMASK; + lzah_bits = (*lzah_getbyte)() & BYTEMASK; + byte |= (lzah_bits >> lzah_bitsavail); + lzah_bits = lzah_bits << (7 - lzah_bitsavail); + } else { + byte = (*lzah_getbyte)() & BYTEMASK; + } + offs = HuffCode[byte]; + skip = HuffLength[byte] - 2; + while(skip-- != 0) { + byte = byte + byte; + lzah_getbit(); + if(lzah_bits & 0x80) { + byte++; + } + } + offs |= (byte & 0x3f); + offs = ((lzah_bufptr - offs - 1) & 0xfff); + ch = ch - 253; + while(ch-- > 0) { + lzah_outchar(lzah_buf[offs++ & 0xfff]); + obytes--; + if(obytes == 0) { + break; + } + } + } + } +} + +static void lzah_inithuf() +{ + int i, j; + + for(i = 0; i < N; i++) { + Frequ[i] = 1; + ForwTree[i] = i + T; + BackTree[i + T] = i; + } + for(i = 0, j = N; j < T; i += 2, j++) { + Frequ[j] = Frequ[i] + Frequ[i + 1]; + ForwTree[j] = i; + BackTree[i] = j; + BackTree[i + 1] = j; + } + Frequ[T] = 0xffff; + BackTree[T - 1] = 0; +} + +static void lzah_reorder() +{ + int i, j, k, l; + + j = 0; + for(i = 0; i < T; i++) { + if(ForwTree[i] >= T) { + Frequ[j] = ((Frequ[i] + 1) >> 1); + ForwTree[j] = ForwTree[i]; + j++; + } + } + for(i = 0, j = N; i < T; i += 2, j++) { + k = i + 1; + l = Frequ[i] + Frequ[k]; + Frequ[j] = l; + k = j - 1; + while(l < Frequ[k]) { + k--; + } + k = k + 1; + lzah_move(Frequ + k, Frequ + k + 1, j - k); + Frequ[k] = l; + lzah_move(ForwTree + k, ForwTree + k + 1, j - k); + ForwTree[k] = i; + } + for(i = 0; i < T; i++) { + k = ForwTree[i]; + if(k >= T) { + BackTree[k] = i; + } else { + BackTree[k] = i; + BackTree[k + 1] = i; + } + } +} + +static void lzah_move(p, q, n) +int *p, *q, n; +{ + if(p > q) { + while(n-- > 0) { + *q++ = *p++; + } + } else { + p += n; + q += n; + while(n-- > 0) { + *--q = *--p; + } + } +} + +static void lzah_getbit() +{ + if(lzah_bitsavail != 0) { + lzah_bits = lzah_bits + lzah_bits; + lzah_bitsavail--; + } else { + lzah_bits = (*lzah_getbyte)() & BYTEMASK; + lzah_bitsavail = 7; + } +} + +static void lzah_outchar(ch) +char ch; +{ + *out_ptr++ = ch; + lzah_buf[lzah_bufptr++] = ch; + lzah_bufptr &= 0xfff; +} +#else /* DELZAH */ +int delzah; /* keep lint and some compilers happy */ +#endif /* DELZAH */ + diff --git a/macunpack/de_lzh.c b/macunpack/de_lzh.c new file mode 100755 index 0000000..9d16177 --- /dev/null +++ b/macunpack/de_lzh.c @@ -0,0 +1,314 @@ +#include "macunpack.h" +#ifdef ZMA +#define DELZH +#endif /* ZMA */ +#ifdef LZH +#define DELZH +#endif /* LZH */ +#ifdef DELZH +#include "globals.h" +#include "../util/masks.h" +#include "../fileio/wrfile.h" +#include "bits_be.h" + +/* This code is valid for bitsused upto 15. */ +#define DICBIT 13 /* 12(-lh4-) or 13(-lh5-) */ +#define UCHAR_MAX 255 +#define THRESHOLD 3 + +static int decoded; +static int bitsused; +static unsigned int blocksize; +static unsigned int decode_c(); +static unsigned int decode_p(); +static void make_table(); + +/* lzh compression */ +void de_lzh(ibytes, obytes, data, bits) +long ibytes; +long obytes; +char **data; +int bits; +{ + unsigned int i, r, c; + int remains; + + bit_be_inbytes = ibytes; + bit_be_filestart = *data; + bitsused = bits; + bit_be_init_getbits(); + blocksize = 0; + decoded = 0; + r = 0; + for(;;) { + c = decode_c(); + if(decoded) { + *data = bit_be_filestart; + return; + } + if(c <= UCHAR_MAX) { + out_ptr[r++] = c; + obytes--; + if(obytes == 0) { + *data = bit_be_filestart; + return; + } + } else { + remains = c - (UCHAR_MAX + 1 - THRESHOLD); + i = (r - decode_p() - 1); + while(--remains >= 0) { + out_ptr[r++] = out_ptr[i++]; + obytes--; + if(obytes == 0) { + *data = bit_be_filestart; + return; + } + } + } + } +} + +#define MAXMATCH 256 +#define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD) +#define CBIT 9 +#define CODE_BIT 16 +#define NP (DICBIT + 1) +#define NT (CODE_BIT + 3) +#define PBIT 4 /* smallest integer such that (1U << PBIT) > NP */ +#define TBIT 5 /* smallest integer such that (1U << TBIT) > NT */ +#if NT > NP +# define NPT NT +#else +# define NPT NP +#endif + +static unsigned int left[2 * NC - 1], right[2 * NC - 1]; +static unsigned char c_len[NC], pt_len[NPT]; +static unsigned int c_table[4096], pt_table[256]; + +static void read_pt_len(nn, nbit, i_special) +int nn; +int nbit; +int i_special; +{ + int i, c, n; + unsigned int mask; + + n = bit_be_getbits(nbit); + if (n == 0) { + c = bit_be_getbits(nbit); + for (i = 0; i < nn; i++) { + pt_len[i] = 0; + } + for (i = 0; i < 256; i++) { + pt_table[i] = c; + } + } else { + i = 0; + while (i < n) { + c = bit_be_bitbuf >> (BITBUFSIZ - 3); + if (c == 7) { + mask = (unsigned) 1 << (BITBUFSIZ - 1 - 3); + while (mask & bit_be_bitbuf) { + mask >>= 1; + c++; + } + } + bit_be_fillbuf((c < 7) ? 3 : c - 3); + pt_len[i++] = c; + if (i == i_special) { + c = bit_be_getbits(2); + while (--c >= 0) { + pt_len[i++] = 0; + } + } + } + while (i < nn) { + pt_len[i++] = 0; + } + make_table(nn, pt_len, 8, pt_table); + } +} + +static void read_c_len() +{ + int i, c, n; + unsigned int mask; + + n = bit_be_getbits(CBIT); + if (n == 0) { + c = bit_be_getbits(CBIT); + for (i = 0; i < NC; i++) { + c_len[i] = 0; + } + for (i = 0; i < 4096; i++) { + c_table[i] = c; + } + } else { + i = 0; + while (i < n) { + c = pt_table[bit_be_bitbuf >> (BITBUFSIZ - 8)]; + if (c >= NT) { + mask = (unsigned) 1 << (BITBUFSIZ - 1 - 8); + do { + if (bit_be_bitbuf & mask) { + c = right[c]; + } else { + c = left [c]; + } + mask >>= 1; + } while (c >= NT); + } + bit_be_fillbuf((int)pt_len[c]); + if (c <= 2) { + if (c == 0) { + c = 1; + } else if (c == 1) { + c = bit_be_getbits(4) + 3; + } else { + c = bit_be_getbits(CBIT) + 20; + } + while (--c >= 0) { + c_len[i++] = 0; + } + } else { + c_len[i++] = c - 2; + } + } + while (i < NC) { + c_len[i++] = 0; + } + make_table(NC, c_len, 12, c_table); + } +} + +static unsigned int decode_c() +{ + unsigned int j, mask; + + if (blocksize == 0) { + blocksize = bit_be_getbits(16); + if (blocksize == 0) { + decoded = 1; + return 0; + } + read_pt_len(NT, TBIT, 3); + read_c_len(); + read_pt_len(bitsused + 1, PBIT, -1); + } + blocksize--; + j = c_table[bit_be_bitbuf >> (BITBUFSIZ - 12)]; + if (j >= NC) { + mask = (unsigned) 1 << (BITBUFSIZ - 1 - 12); + do { + if (bit_be_bitbuf & mask) { + j = right[j]; + } else { + j = left [j]; + } + mask >>= 1; + } while (j >= NC); + } + bit_be_fillbuf((int)c_len[j]); + return j; +} + +static unsigned int decode_p() +{ + unsigned int j, mask; + + j = pt_table[bit_be_bitbuf >> (BITBUFSIZ - 8)]; + if (j > bitsused) { + mask = (unsigned) 1 << (BITBUFSIZ - 1 - 8); + do { + if (bit_be_bitbuf & mask) { + j = right[j]; + } else { + j = left [j]; + } + mask >>= 1; + } while (j > bitsused); + } + bit_be_fillbuf((int)pt_len[j]); + if (j != 0) { + j = ((unsigned) 1 << (j - 1)) + bit_be_getbits((int) (j - 1)); + } + return j; +} + +static void make_table(nchar, bitlen, tablebits, table) +int nchar; +unsigned char bitlen[]; +int tablebits; +unsigned int table[]; +{ + unsigned int count[17], weight[17], start[18], *p; + unsigned int i, k, len, ch, jutbits, avail, nextcode, mask; + + for (i = 1; i <= 16; i++) { + count[i] = 0; + } + for (i = 0; i < nchar; i++) { + count[bitlen[i]]++; + } + + start[1] = 0; + for (i = 1; i <= 16; i++) { + start[i + 1] = start[i] + (count[i] << (16 - i)); + } + + jutbits = 16 - tablebits; + for (i = 1; i <= tablebits; i++) { + start[i] >>= jutbits; + weight[i] = (unsigned) 1 << (tablebits - i); + } + while (i <= 16) { + weight[i] = (unsigned) 1 << (16 - i); + i++; + } + + i = start[tablebits + 1] >> jutbits; + if (i != (unsigned int)((unsigned) 1 << 16)) { + k = 1 << tablebits; + while (i != k) { + table[i++] = 0; + } + } + + avail = nchar; + mask = (unsigned) 1 << (15 - tablebits); + for (ch = 0; ch < nchar; ch++) { + if ((len = bitlen[ch]) == 0) { + continue; + } + nextcode = start[len] + weight[len]; + if (len <= tablebits) { + for (i = start[len]; i < nextcode; i++) { + table[i] = ch; + } + } else { + k = start[len]; + p = &table[k >> jutbits]; + i = len - tablebits; + while (i != 0) { + if (*p == 0) { + right[avail] = left[avail] = 0; + *p = avail++; + } + if (k & mask) { + p = &right[*p]; + } else { + p = &left[*p]; + } + k <<= 1; + i--; + } + *p = ch; + } + start[len] = nextcode; + } +} +#else /* DELZH */ +int delzh; /* keep lint and some compilers happy */ +#endif /* DELZH */ + diff --git a/macunpack/dia.c b/macunpack/dia.c new file mode 100755 index 0000000..984eff3 --- /dev/null +++ b/macunpack/dia.c @@ -0,0 +1,558 @@ +#include "macunpack.h" +#ifdef DIA +#include "globals.h" +#include "dia.h" +#include "../util/curtime.h" +#include "../util/masks.h" +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "../fileio/kind.h" +#include "../util/util.h" + +extern char *malloc(); +extern char *realloc(); + +static unsigned char *dia_archive; +static int dia_archive_size; +static int dia_max_archive_size; +static int dia_finfo; +static int dia_method; +static unsigned char *dia_archive_ptr; +static unsigned char *dia_header_ptr; +static unsigned char *dia_header_last; +static int dia_forklength; +static int dia_cforklength; +static unsigned char dia_bitbuf[BCHUNKSIZE]; +static int dia_LZtab[BCHUNKSIZE]; +static unsigned char *dia_bit_base; +static int dia_imask; + +static void dia_folder(); +static void dia_file(); +static void dia_getlength(); +static void dia_skipfork(); +static void dia_getfork(); +static void dia_getblock(); +static int dia_decode(); +static int dia_prevbit(); + +void dia(bin_hdr) +unsigned char *bin_hdr; +{ + int i, folder, nlength; + unsigned char hdr; + unsigned char *header; + + dir_skip = 0; + for(i = 0; i < INFOBYTES; i++) { + info[i] = 0; + } + if(in_data_size > dia_max_archive_size) { + if(dia_archive == NULL) { + dia_archive = (unsigned char *)malloc((unsigned)in_data_size); + } else { + dia_archive = (unsigned char *)realloc((char *)dia_archive, + (unsigned)in_data_size); + } + if(dia_archive == 0) { + (void)fprintf(stderr, "Insufficient memory.\n"); + exit(1); + } + dia_max_archive_size = in_data_size; + } + dia_archive_size = in_data_size; + if(fread((char *)dia_archive, 1, in_data_size, infp) != in_data_size) { + (void)fprintf(stderr, "Can't read archive.\n"); +#ifdef SCAN + do_error("macunpack: Can't read archive"); +#endif /* SCAN */ + exit(1); + } + nlength = bin_hdr[I_NAMEOFF] & BYTEMASK; + if(!strncmp((char *)bin_hdr + I_NAMEOFF + nlength - 1, " \272", 2)) { + nlength -= 2; + } + info[I_NAMEOFF] = nlength; + for(i = 1; i <= nlength; i++) { + info[I_NAMEOFF + i] = bin_hdr[I_NAMEOFF + i]; + } + hdr = *dia_archive; + folder = hdr & IS_FOLDER; + dia_finfo = hdr & F_INFO; + if(hdr & VOLUME) { + (void)fprintf(stderr, "Multi-segment archives not implemented.\n"); +#ifdef SCAN + do_error("macunpack: Multi-segment archive"); +#endif /* SCAN */ + exit(1); + } + if(hdr & CRYPTED) { + (void)fprintf(stderr, "Encrypted archives not implemented.\n"); +#ifdef SCAN + do_idf("", PROTECTED); +#endif /* SCAN */ + exit(1); + } + i = (hdr & N_BLOCKS) + 1; + header = (unsigned char *)malloc((unsigned)(i * CHUNKSIZE)); + dia_archive_ptr = dia_archive + 1; + dia_header_last = header; + dia_method = 0; + while(i-- > 0) { + dia_getblock(&dia_archive_ptr, &dia_header_last); + } + dia_header_ptr = header; + if(folder) { + dia_folder((unsigned char *)NULL); + } else { + dia_file(*dia_header_ptr++, (unsigned char *)NULL); + } + free((char *)header); +} + +static void dia_folder(name) +unsigned char *name; +{ + unsigned char lname[32]; + int i, length, doit; + unsigned char indicator, *old_ptr; + + if(name != NULL) { + for(i = 0; i < INFOBYTES; i++) { + info[i] = 0; + } + length = *name++ & REMAINS; + info[I_NAMEOFF] = length; + for(i = 1; i <= length; i++) { + info[I_NAMEOFF + i] = *name++; + } + } else { + length = info[I_NAMEOFF]; + } + if(dia_finfo) { + dia_header_ptr += 20; + } + if(!dir_skip) { + doit = 1; + if(list) { + transname(info + I_NAMEOFF + 1, (char *)lname, length); + do_indent(indent); + (void)fprintf(stderr, "folder=\"%s\"", lname); + if(query) { + doit = do_query(); + } else { + (void)fputc('\n', stderr); + } + if(doit) { + indent++; + } else { + dir_skip = 1; + } + } + if(doit && !info_only) { + do_mkdir((char *)lname, info); + } + } else { + dir_skip++; + } + while(dia_header_ptr < dia_header_last) { + indicator = *dia_header_ptr; + if(indicator & LEAVE_FOLDER) { + *dia_header_ptr = indicator & ~LEAVE_FOLDER; + break; + } else if(indicator & ONLY_FOLDER) { + if(indicator == ONLY_FOLDER) { + dia_header_ptr++; + } else { + *dia_header_ptr -= 1; + } + break; + } else if(indicator & FOLDER) { + old_ptr = dia_header_ptr; + dia_header_ptr += (indicator & REMAINS) + 1; + dia_folder(old_ptr); + } else { + dia_header_ptr++; + old_ptr = dia_header_ptr; + dia_header_ptr += (*old_ptr & REMAINS) + 1; + dia_file(indicator, old_ptr); + } + } + if(!dir_skip) { + if(doit) { + indent--; + if(!info_only) { + enddir(); + } + do_indent(indent); + (void)fprintf(stderr, "leaving folder \"%s\"\n", lname); + } + } else { + dir_skip--; + } +} + +static void dia_file(indicator, name) +unsigned char indicator, *name; +{ + unsigned char lname[32]; + int i, length, doit; + int n_data, n_rsrc; + unsigned char *old_archive_ptr; + char ftype[5], fauth[5]; + int dataLength, rsrcLength; + int cdataLength, crsrcLength; + int dataMethod, rsrcMethod; + unsigned long curtime; + + if(name != NULL) { + for(i = 0; i < INFOBYTES; i++) { + info[i] = 0; + } + length = *name++ & REMAINS; + info[I_NAMEOFF] = length; + for(i = 1; i <= length; i++) { + info[I_NAMEOFF + i] = *name++; + } + } else { + length = info[I_NAMEOFF]; + } + for(i = 0; i < 4; i++) { + info[I_TYPEOFF + i] = *dia_header_ptr++; + } + for(i = 0; i < 4; i++) { + info[I_AUTHOFF + i] = *dia_header_ptr++; + } + if(indicator & DATE_PRESENT) { + for(i = 0; i < 4; i++) { + info[I_CTIMOFF + i] = *dia_header_ptr++; + } + for(i = 0; i < 4; i++) { + info[I_MTIMOFF + i] = *dia_header_ptr++; + } + } else { + curtime = (unsigned long)time((time_t *)0) + TIMEDIFF; + put4(info + I_CTIMOFF, curtime); + put4(info + I_MTIMOFF, curtime); + } + if(dia_finfo) { + for(i = 0; i < 6; i++) { + info[I_FLAGOFF + i] = *dia_header_ptr++; + } + } + n_data = 0; + if(indicator & HAS_DATA) { + if(indicator & SHORT_DATA) { + n_data = 1; + } else { + n_data = *dia_header_ptr++ + 1; + } + } + n_rsrc = 0; + if(indicator & HAS_RSRC) { + if(indicator & SHORT_RSRC) { + n_rsrc = 1; + } else { + n_rsrc = *dia_header_ptr++ + 1; + } + } + if(!dir_skip) { + old_archive_ptr = dia_archive_ptr; + dia_getlength(n_data); + dataLength = dia_forklength; + cdataLength = dia_cforklength; + dataMethod = dia_method; + dia_getlength(n_rsrc); + rsrcLength = dia_forklength; + crsrcLength = dia_cforklength; + rsrcMethod = dia_method; + dia_archive_ptr = old_archive_ptr; + put4(info + I_DLENOFF, (unsigned long)dataLength); + put4(info + I_RLENOFF, (unsigned long)rsrcLength); + if(list) { + transname(info + I_NAMEOFF + 1, (char *)lname, length); + do_indent(indent); + transname(info + I_TYPEOFF, ftype, 4); + transname(info + I_AUTHOFF, fauth, 4); + (void)fprintf(stderr, + "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld", + lname, ftype, fauth, (long)dataLength, (long)rsrcLength); + if(info_only) { + doit = 0; + } else { + doit = 1; + } + if(query) { + doit = do_query(); + } else { + (void)fputc('\n', stderr); + } + } else { + doit = 1; + } + } else { + dia_skipfork(n_data); + dia_skipfork(n_rsrc); + return; + } + if(doit) { + define_name((char *)lname); + start_info(info, (unsigned long)rsrcLength, (unsigned long)dataLength); + } + if(verbose) { + (void)fprintf(stderr, "\tData: "); + if(dataLength == 0) { + (void)fprintf(stderr, "empty"); + } else if(dataMethod == NOCOMP) { + (void)fprintf(stderr, "No compression"); + } else { + if(dataMethod != COMP) { + (void)fprintf(stderr, "Partial "); + } + (void)fprintf(stderr, "LZFK compressed (%4.1f%%)", + 100.0 * cdataLength / dataLength); + } + } + if(doit) { + start_data(); + dia_getfork(n_data); + } else { + dia_skipfork(n_data); + } + if(verbose) { + (void)fprintf(stderr, ", Rsrc: "); + if(rsrcLength == 0) { + (void)fprintf(stderr, "empty"); + } else if(rsrcMethod == NOCOMP) { + (void)fprintf(stderr, "No compression"); + } else { + if(rsrcMethod != COMP) { + (void)fprintf(stderr, "Partial "); + } + (void)fprintf(stderr, "LZFK compressed (%4.1f%%)", + 100.0 * crsrcLength / rsrcLength); + } + } + if(doit) { + start_rsrc(); + dia_getfork(n_rsrc); + } else { + dia_skipfork(n_rsrc); + } + if(verbose) { + (void)fprintf(stderr, ".\n"); + } + if(doit) { + end_file(); + } +} + +static void dia_getlength(nblocks) +int nblocks; +{ + int length; + unsigned char *arch_ptr, *block_ptr; + unsigned char block[CHUNKSIZE]; + + dia_method = 0; + dia_forklength = 0; + dia_cforklength = 0; + while(nblocks > 1) { + nblocks--; + length = get2((char *)dia_archive_ptr); + if(length >= 0x8000) { + length = 0x10000 - length; + dia_method |= NOCOMP; + } else { + dia_method |= COMP; + } + dia_forklength += CHUNKSIZE; + dia_cforklength += length + 2; + dia_archive_ptr += length + 2; + } + if(nblocks == 1) { + arch_ptr = dia_archive_ptr; + block_ptr = block; + dia_getblock(&arch_ptr, &block_ptr); + dia_forklength += block_ptr - block; + dia_cforklength += arch_ptr - dia_archive_ptr; + dia_archive_ptr = arch_ptr; + } +} + +static void dia_skipfork(nblocks) +int nblocks; +{ + int length; + + while(nblocks-- > 0) { + length = get2((char *)dia_archive_ptr); + if(length >= 0x8000) { + length = 0x10000 - length; + } + dia_archive_ptr += length + 2; + } +} + +static void dia_getfork(nblocks) +int nblocks; +{ + while(nblocks-- > 0) { + dia_getblock(&dia_archive_ptr, (unsigned char **)&out_ptr); + } +} + +static void dia_getblock(archive_ptr, block_ptr) +unsigned char **archive_ptr, **block_ptr; +{ + int length, i; + unsigned char *arch_ptr, *bl_ptr; + + arch_ptr = *archive_ptr; + bl_ptr = *block_ptr; + length = get2((char *)arch_ptr); + arch_ptr += 2; + if(length >= 0x8000) { + length = 0x10000 - length; + for(i = 0; i < length; i++) { + *bl_ptr++ = *arch_ptr++; + } + *block_ptr += length; + dia_method |= NOCOMP; + } else { + *block_ptr += dia_decode(arch_ptr, bl_ptr, length); + dia_method |= COMP; + } + *archive_ptr += length + 2; +} + +static int dia_decode(ibuff, obuff, in_length) +unsigned char *ibuff, *obuff; int in_length; +{ + int nbits, set_zero, i, j; + unsigned char *bitbuf_ptr; + int count[4]; + int *LZtab_ptr; + unsigned char *out_ptr, *buf_ptr, *in_ptr; + int omask; + int LZcount; + int *length_ptr, *nchars_ptr; + int *offsn_ptr, length, nchars, offset; + int *offs_ptr[4]; + int nwords; + + in_ptr = ibuff + in_length; + nbits = *--in_ptr; + nbits |= (*--in_ptr << 8); + if(nbits == WORDMASK) { + nbits = *--in_ptr; + nbits |= (*--in_ptr << 8); + nbits = nbits + WORDMASK; + } + bitbuf_ptr = dia_bitbuf + BCHUNKSIZE; + *--bitbuf_ptr = *--in_ptr; + set_zero = 0; + dia_bit_base = bitbuf_ptr; + dia_imask = 1 << (7 - (nbits & 7)); + if(dia_prevbit()) { + set_zero = 1; + } + for(i = 0; i < nbits; i++) { + if(set_zero) { + *--bitbuf_ptr = 0; + } else { + *--bitbuf_ptr = *--in_ptr; + } + if(dia_prevbit()) { + set_zero = !set_zero; + } + } + /* Now we have the bits in longitudal order; reorder them */ + nwords = ((dia_bit_base - bitbuf_ptr) >> 1); + for(i = 0; i < nwords; i++) { + dia_LZtab[i] = 0; + } + omask = 1; + for(i = 0; i < 16; i++) { + j = nwords; + LZtab_ptr = dia_LZtab + nwords; + while(j-- > 0) { + LZtab_ptr--; + if(dia_prevbit()) { + *LZtab_ptr |= omask; + } + } + omask <<= 1; + } + LZcount = nwords / 3; + /* At this point we have in LZtab LZcount triples. Each triple consists + of the following parts: + nchars: the number of characters to take from input + length: the number of characters - 1 to copy from output + offset: the offset in the output buffer + The ordering is as follows: + 1. lengths + 2. nchars + 3. offsets for length 0 + 4. offsets for length 1 + 5. offsets for length 2 + 6. offsets for length 3 + 7. offsets for other lengths + */ + /* Now first count the occurences of lengths 0 to 3 */ + count[0] = 0; + count[1] = 0; + count[2] = 0; + count[3] = 0; + for(i = 0; i < LZcount; i++) { + if((j = dia_LZtab[i]) < 4) { + count[j]++; + } + } + length_ptr = dia_LZtab; + nchars_ptr = dia_LZtab + LZcount; + offs_ptr[0] = nchars_ptr + LZcount; + offs_ptr[1] = offs_ptr[0] + count[0]; + offs_ptr[2] = offs_ptr[1] + count[1]; + offs_ptr[3] = offs_ptr[2] + count[2]; + offsn_ptr = offs_ptr[3] + count[3]; + out_ptr = obuff; + for(i = 0; i < LZcount; i++) { + length = *length_ptr++; + nchars = *nchars_ptr++; + if(length < 4) { + offset = *offs_ptr[length]++; + } else { + offset = *offsn_ptr++; + } + while(nchars-- > 0) { + *out_ptr++ = *ibuff++; + } + buf_ptr = out_ptr - length - offset - 1; + while(length-- >= 0) { + *out_ptr++ = *buf_ptr++; + } + } + i = in_ptr - ibuff; + while(i-- > 0) { + *out_ptr++ = *ibuff++; + } + return out_ptr - obuff; +} + +static int dia_prevbit() +{ + int c; + + if(dia_imask == 0x100) { + dia_bit_base--; + dia_imask = 1; + } + c = *dia_bit_base & dia_imask; + dia_imask <<= 1; + return c; +} +#else /* DIA */ +int dia; /* keep lint and some compilers happy */ +#endif /* DIA */ + diff --git a/macunpack/dia.h b/macunpack/dia.h new file mode 100755 index 0000000..10c73e2 --- /dev/null +++ b/macunpack/dia.h @@ -0,0 +1,22 @@ +#define IS_FOLDER 0x80 +#define F_INFO 0x40 +#define VOLUME 0x30 +#define CRYPTED 0x08 +#define N_BLOCKS 0x07 + +#define LEAVE_FOLDER 0x80 +#define ONLY_FOLDER 0x40 +#define FOLDER 0x20 +#define DATE_PRESENT 0x10 +#define HAS_DATA 0x08 +#define HAS_RSRC 0x04 +#define SHORT_DATA 0x02 +#define SHORT_RSRC 0x01 +#define REMAINS 0x1f + +#define CHUNKSIZE 32767 +#define BCHUNKSIZE (CHUNKSIZE * 16 / 7) + +#define NOCOMP 1 +#define COMP 2 + diff --git a/macunpack/dia.o b/macunpack/dia.o new file mode 100644 index 0000000..43618db Binary files /dev/null and b/macunpack/dia.o differ diff --git a/macunpack/dir.c b/macunpack/dir.c new file mode 100755 index 0000000..494b395 --- /dev/null +++ b/macunpack/dir.c @@ -0,0 +1,75 @@ +#include "globals.h" +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "../util/util.h" +#include "../util/masks.h" + +extern char *malloc(); +extern char *realloc(); + +static char *dir_stack; +static int dir_ptr = -64; +static int dir_max; + +void dir(hdr) +char *hdr; +{ +int doit; + + if((hdr[I_NAMEOFF] & BYTEMASK) == 0x80) { + if(dir_skip) { + dir_skip--; + return; + } + indent--; + if(list) { + do_indent(indent); + (void)fprintf(stderr, "leaving folder \"%s\"\n", + dir_stack + dir_ptr); + } + if(!info_only) { + enddir(); + } + dir_ptr -= 64; + return; + } + if(dir_skip) { + dir_skip++; + return; + } + dir_ptr += 64; + if(dir_ptr == dir_max) { + if(dir_max == 0) { + dir_stack = malloc(64); + } else { + dir_stack = realloc(dir_stack, (unsigned)dir_max + 64); + } + dir_max += 64; + if(dir_stack == NULL) { + (void)fprintf(stderr, "Insufficient memory\n"); + exit(1); + } + } + transname(hdr + I_NAMEOFF + 1, dir_stack + dir_ptr, + (int)(hdr[I_NAMEOFF] & 0x7f)); + doit = 1; + if(list) { + do_indent(indent); + (void)fprintf(stderr, "folder=\"%s\"", dir_stack + dir_ptr); + if(query) { + doit = do_query(); + } else { + (void)fputc('\n', stderr); + } + } + if(!doit) { + dir_ptr -= 64; + dir_skip = 1; + return; + } + if(!info_only) { + do_mkdir(dir_stack + dir_ptr, hdr); + } + indent++; +} + diff --git a/macunpack/dir.o b/macunpack/dir.o new file mode 100644 index 0000000..1a00d4a Binary files /dev/null and b/macunpack/dir.o differ diff --git a/macunpack/globals.c b/macunpack/globals.c new file mode 100755 index 0000000..d878a7b --- /dev/null +++ b/macunpack/globals.c @@ -0,0 +1,22 @@ +#include "globals.h" +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "../fileio/kind.h" + +char info[INFOBYTES]; +char text[F_NAMELEN+1]; + +int list, verbose, info_only, query, write_it, indent, dir_skip, no_dd; +FILE *infp; +int in_data_size = -1; +int in_rsrc_size = -1; +int in_ds, in_rs, ds_skip, rs_skip; + +#ifdef SCAN +void do_error(string) +char *string; +{ + do_idf(string, ERROR); +} +#endif /* SCAN */ + diff --git a/macunpack/globals.h b/macunpack/globals.h new file mode 100755 index 0000000..e431048 --- /dev/null +++ b/macunpack/globals.h @@ -0,0 +1,14 @@ +#include + +extern void exit(); +extern void transname(); +extern void do_error(); + +extern char info[]; +extern char text[]; + +extern int list, verbose, info_only, query, write_it, indent, dir_skip, no_dd; +extern FILE *infp; + +extern int in_data_size, in_rsrc_size, in_ds, in_rs, ds_skip, rs_skip; + diff --git a/macunpack/globals.o b/macunpack/globals.o new file mode 100644 index 0000000..ca68861 Binary files /dev/null and b/macunpack/globals.o differ diff --git a/macunpack/huffman.h b/macunpack/huffman.h new file mode 100755 index 0000000..7a678f6 --- /dev/null +++ b/macunpack/huffman.h @@ -0,0 +1,14 @@ +#define HUFF_BE 0 +#define HUFF_LE 1 + +typedef struct node { + int flag, byte; + struct node *one, *zero; +} node; + +extern int (*get_bit)(); +extern void clrhuff(); + +extern struct node nodelist[]; +extern int bytesread; + diff --git a/macunpack/jdw.c b/macunpack/jdw.c new file mode 100755 index 0000000..e479994 --- /dev/null +++ b/macunpack/jdw.c @@ -0,0 +1,160 @@ +#include "macunpack.h" +#ifdef JDW +#include "jdw.h" +#include "globals.h" +#include "huffman.h" +#include "../fileio/wrfile.h" +#include "../fileio/machdr.h" +#include "../util/util.h" +#include "../util/masks.h" + +extern void de_huffman(); +extern void set_huffman(); +extern void read_tree(); +extern void clrhuff(); + +static void jdw_wrfile(); +static void jdw_wrfork(); +static void jdw_block(); + +void jdw(ibytes) +unsigned long ibytes; +{ + char fauth[5], ftype[5]; + int filel, i; + unsigned int rsrcLength, dataLength; + + set_huffman(HUFF_BE); + for(i = 0; i < 6; i++) (void)getb(infp); + for(i = 0; i < INFOBYTES; i++) { + info[i] = 0; + } + for(i = 0; i < 4; i++) { + info[I_TYPEOFF + i] = getb(infp); + } + for(i = 0; i < 4; i++) { + info[I_AUTHOFF + i] = getb(infp); + } + for(i = 0; i < 8; i++) { + info[I_FLAGOFF + i] = getb(infp); + } + for(i = 0; i < 4; i++) { + info[I_DLENOFF + i] = getb(infp); + } + for(i = 0; i < 4; i++) { + info[I_RLENOFF + i] = getb(infp); + } + for(i = 0; i < 4; i++) { + info[I_CTIMOFF + i] = getb(infp); + } + for(i = 0; i < 4; i++) { + info[I_MTIMOFF + i] = getb(infp); + } + filel = getb(infp); + info[I_NAMEOFF] = filel; + i = filel; + for(i = 1; i <= filel; i++) { + info[I_NAMEOFF + i] = getb(infp); + } + (void)getb(infp); + rsrcLength = get4(info + I_RLENOFF); + dataLength = get4(info + I_DLENOFF); + ibytes -= filel + 40; + write_it = 1; + if(list) { + transname(info + I_NAMEOFF + 1, text, (int)info[I_NAMEOFF]); + transname(info + I_TYPEOFF, ftype, 4); + transname(info + I_AUTHOFF, fauth, 4); + do_indent(indent); + (void)fprintf(stderr, + "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld", + text, ftype, fauth, (long)dataLength, (long)rsrcLength); + if(info_only) { + write_it = 0; + } + if(query) { + write_it = do_query(); + } else { + (void)fputc('\n', stderr); + } + } + jdw_wrfile((unsigned long)rsrcLength, (unsigned long)dataLength); +} + +static void jdw_wrfile(rsrcLength, dataLength) +unsigned long rsrcLength, dataLength; +{ + if(write_it) { + define_name(text); + start_info(info, rsrcLength, dataLength); + start_data(); + } + if(verbose) { + (void)fprintf(stderr, "\tData: "); + } + jdw_wrfork(dataLength); + if(write_it) { + start_rsrc(); + } + if(verbose) { + (void)fprintf(stderr, ", Rsrc: "); + } + jdw_wrfork(rsrcLength); + if(write_it) { + end_file(); + } + if(verbose) { + (void)fprintf(stderr, ".\n"); + } +} + +static void jdw_wrfork(length) +unsigned long length; +{ + int olength, ilength, i; + unsigned long origlength, comprlength; + + if(length == 0) { + (void)fprintf(stderr, "empty"); + return; + } + (void)fprintf(stderr, "Huffman compressed "); + comprlength = 0; + origlength = length; + while(length > 0) { + olength = getb(infp) & BYTEMASK; + olength = (olength << 8) | (getb(infp) & BYTEMASK); + ilength = getb(infp) & BYTEMASK; + ilength = (ilength << 8) | (getb(infp) & BYTEMASK); + if(write_it) { + jdw_block(olength); + } else { + for(i = 0; i < ilength; i++) { + (void)getb(infp); + } + } + comprlength += ilength + 4; + length -= olength; + } + if(verbose) { + (void)fprintf(stderr, "(%4.1f%%)", 100.0 * comprlength / origlength); + } +} + +static void jdw_block(olength) +int olength; +{ + bytesread = 0; + read_tree(); + /* Put reading back at a word boundary! */ + while(bytesread & 3) { + (void)getb(infp); + bytesread++; + } + clrhuff(); + de_huffman((unsigned long)olength); +} +#else /* JDW */ +int jdw; /* keep lint and some compilers happy */ +#endif /* JDW */ + diff --git a/macunpack/jdw.h b/macunpack/jdw.h new file mode 100755 index 0000000..545c365 --- /dev/null +++ b/macunpack/jdw.h @@ -0,0 +1,23 @@ +#define J_MAGIC 0 +#define J_TYPE 6 +#define J_AUTH 10 +#define J_FINFO 14 +#define J_DATALENGTH 22 +#define J_RSRCLENGTH 26 +#define J_CTIME 30 +#define J_MTIME 34 +#define J_FLENGTH 38 + +typedef struct fileHdr { + char magic[6]; + unsigned long type; + unsigned long auth; + char finfo[8]; + unsigned long dataLength; + unsigned long rsrcLength; + unsigned long ctime; + unsigned long mtime; + char flength; + char fname[32]; /* actually flength */ +}; + diff --git a/macunpack/jdw.o b/macunpack/jdw.o new file mode 100644 index 0000000..4d04e71 Binary files /dev/null and b/macunpack/jdw.o differ diff --git a/macunpack/lzc.c b/macunpack/lzc.c new file mode 100755 index 0000000..08e26ff --- /dev/null +++ b/macunpack/lzc.c @@ -0,0 +1,196 @@ +#include "macunpack.h" +#ifdef LZC +#include "globals.h" +#include "lzc.h" +#include "../util/util.h" +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "../util/masks.h" + +extern void de_compress(); +extern void core_compress(); +extern void mcb(); + +static void lzc_zivm(); +static void lzc_wrfile(); +static void lzc_zivu(); + +void lzc(ohdr) +char *ohdr; +{ + core_compress((char *)NULL); + if(!strncmp(ohdr + I_TYPEOFF, "ZIVM", 4)) { + lzc_zivm(ohdr); + } else { + lzc_zivu(ohdr); + } +} + +static void lzc_zivm(ohdr) +char *ohdr; +{ + char hdr[HEADERBYTES]; + unsigned long dataLength, rsrcLength, dataCLength, rsrcCLength; + char ftype[5], fauth[5]; + + if(fread(hdr, 1, HEADERBYTES, infp) != HEADERBYTES) { + (void)fprintf(stderr, "Can't read file header\n"); +#ifdef SCAN + do_error("macunpack: Can't read file header"); +#endif /* SCAN */ + exit(1); + } + if(strncmp(hdr, MAGIC1, 4)) { + (void)fprintf(stderr, "Magic header mismatch\n"); +#ifdef SCAN + do_error("macunpack: Magic header mismatch"); +#endif /* SCAN */ + exit(1); + } + dataLength = get4(hdr + C_DLENOFF); + dataCLength = get4(hdr + C_DLENOFFC); + rsrcLength = get4(hdr + C_RLENOFF); + rsrcCLength = get4(hdr + C_RLENOFFC); + + write_it = 1; + if(list) { + copy(info, ohdr, INFOBYTES); + copy(info + I_TYPEOFF, hdr + C_TYPEOFF, 4); + copy(info + I_AUTHOFF, hdr + C_AUTHOFF, 4); + copy(info + I_DLENOFF, hdr + C_DLENOFF, 4); + copy(info + I_RLENOFF, hdr + C_RLENOFF, 4); + copy(info + I_CTIMOFF, hdr + C_CTIMOFF, 4); + copy(info + I_MTIMOFF, hdr + C_MTIMOFF, 4); + copy(info + I_FLAGOFF, hdr + C_FLAGOFF, 8); + + transname(ohdr + I_NAMEOFF + 1, text, (int)ohdr[I_NAMEOFF]); + transname(hdr + C_TYPEOFF, ftype, 4); + transname(hdr + C_AUTHOFF, fauth, 4); + do_indent(indent); + (void)fprintf(stderr, + "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld", + text, ftype, fauth, (long)dataLength, (long)rsrcLength); + if(info_only) { + write_it = 0; + } + if(query) { + write_it = do_query(); + } else { + (void)fputc('\n', stderr); + } + } + + if(write_it) { + define_name(text); + } + if(write_it) { + start_info(info, rsrcLength, dataLength); + } + if(verbose) { + (void)fprintf(stderr, "\tData: "); + } + if(write_it) { + start_data(); + } + lzc_wrfile(dataLength, dataCLength); + if(verbose) { + (void)fprintf(stderr, ", Rsrc: "); + } + if(write_it) { + start_rsrc(); + } + lzc_wrfile(rsrcLength, rsrcCLength); + if(write_it) { + end_file(); + } + if(verbose) { + (void)fprintf(stderr, ".\n"); + } +} + +static void lzc_wrfile(obytes, ibytes) +unsigned long obytes, ibytes; +{ + int n, nbits; + char subheader[3]; + + if(ibytes == 0) { + if(verbose) { + (void)fprintf(stderr, "empty"); + } + return; + } + if(ibytes == obytes) { + if(verbose) { + (void)fprintf(stderr, "No compression"); + } + if(write_it) { + n = fread(out_buffer, 1, (int)ibytes, infp); + if(n != ibytes) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("macunpack: Premature EOF"); +#endif /* SCAN */ + exit(1); + } + } else { + n = ibytes; + while(n-- > 0) { + if(getc(infp) == EOF) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("macunpack: Premature EOF"); +#endif /* SCAN */ + exit(1); + } + } + } + } else { + if(fread(subheader, 1, 3, infp) != 3) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("macunpack: Premature EOF"); +#endif /* SCAN */ + exit(1); + } + if(strncmp(subheader, MAGIC2, 2)) { + (void)fprintf(stderr, "Magic subheader mismatch\n"); +#ifdef SCAN + do_error("macunpack: Magic subheader mismatch"); +#endif /* SCAN */ + exit(1); + } + nbits = subheader[2] & 0x7f; + if(verbose) { + (void)fprintf(stderr, "LZC(%d) compressed (%4.1f%%)", + nbits, 100.0 * ibytes / obytes); + } + if(write_it) { + de_compress(ibytes - 3, nbits); + } else { + n = ibytes - 3; + while(n-- > 0) { + if(getc(infp) == EOF) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("macunpack: Premature EOF"); +#endif /* SCAN */ + exit(1); + } + } + } + } +} + +static void lzc_zivu(ohdr) +char *ohdr; +{ + (void)fprintf(stderr, + "\tMacCompress(Unix) not yet implemented, copied as MacBinary\n"); + mcb(ohdr, (unsigned long)in_rsrc_size, (unsigned long)in_data_size, + in_ds + in_rs); +} +#else /* LZC */ +int lzc; /* keep lint and some compilers happy */ +#endif /* LZC */ + diff --git a/macunpack/lzc.h b/macunpack/lzc.h new file mode 100755 index 0000000..daa6d86 --- /dev/null +++ b/macunpack/lzc.h @@ -0,0 +1,29 @@ +#define HEADERBYTES 48 +#define MAGIC1 "\253\315\000\060" +#define MAGIC2 "\037\235" + +#define C_DLENOFF 4 +#define C_DLENOFFC 8 +#define C_RLENOFF 12 +#define C_RLENOFFC 16 +#define C_MTIMOFF 24 +#define C_CTIMOFF 28 +#define C_TYPEOFF 32 +#define C_AUTHOFF 36 +#define C_FLAGOFF 40 + +typedef struct fileHdr { + unsigned long magic1; + unsigned long dataLength; + unsigned long dataCLength; + unsigned long rsrcLength; + unsigned long rsrcCLength; + unsigned long unknown1; + unsigned long mtime; + unsigned long ctime; + unsigned long filetype; + unsigned long fileauth; + unsigned long flag1; + unsigned long flag2; +}; + diff --git a/macunpack/lzc.o b/macunpack/lzc.o new file mode 100644 index 0000000..10f3aae Binary files /dev/null and b/macunpack/lzc.o differ diff --git a/macunpack/lzh.c b/macunpack/lzh.c new file mode 100755 index 0000000..136f8d1 --- /dev/null +++ b/macunpack/lzh.c @@ -0,0 +1,776 @@ +#include "macunpack.h" +#ifdef LZH +#include "globals.h" +#include "lzh.h" +#include "crc.h" +#include "../fileio/wrfile.h" +#include "../fileio/machdr.h" +#include "../util/masks.h" +#include "../util/util.h" +#include "bits_be.h" + +#define LZ5LOOKAHEAD 18 /* look ahead buffer size for LArc */ +#define LZ5BUFFSIZE 8192 +#define LZ5MASK 8191 +#define LZSLOOKAHEAD 17 +#define LZSBUFFSIZE 4096 +#define LZSMASK 4095 +#define LZBUFFSIZE 8192 /* Max of above buffsizes */ + +extern char *malloc(); +extern char *realloc(); +extern void de_lzah(); +extern unsigned char (*lzah_getbyte)(); +extern void de_lzh(); + +typedef struct methodinfo { + char *name; + int number; +}; + +static struct methodinfo methods[] = { + {"-lh0-", lh0}, + {"-lh1-", lh1}, + {"-lh2-", lh2}, + {"-lh3-", lh3}, + {"-lh4-", lh4}, + {"-lh5-", lh5}, + {"-lz4-", lz4}, + {"-lz5-", lz5}, + {"-lzs-", lzs} +}; +static char *lzh_archive; +static char *lzh_pointer; +static char *lzh_data; +static char *lzh_finfo; +static int lzh_fsize; +static int lzh_kind; +static int oldsize; +static char *lzh_file; +static int lzh_filesize; +static char *lzh_current; +static char *tmp_out_ptr; +static char lzh_lzbuf[LZBUFFSIZE]; + +static int lzh_filehdr(); +static int lzh_checkm(); +static char *lzh_methname(); +static void lzh_wrfile(); +static void lzh_skip(); +static void lzh_nocomp(); +#ifdef UNTESTED +static void lzh_lzss1(); +static void lzh_lzss2(); +#endif /* UNTESTED */ +static void lzh_lzah(); +static unsigned char lzh_getbyte(); +#ifdef UNDEF +static void lzh_lh2(); +static void lzh_lh3(); +#endif /* UNDEF */ +#ifdef UNTESTED +static void lzh_lzh12(); +#endif /* UNTESTED */ +static void lzh_lzh13(); + +void lzh(kind) +int kind; +{ + struct fileHdr filehdr; + int m, i, j; + char loc_name[64]; + char dirinfo[INFOBYTES]; + + updcrc = arc_updcrc; + crcinit = arc_crcinit; + write_it = 1; + lzh_fsize = 0; + lzh_kind = kind; + if(lzh_archive == NULL) { + lzh_archive = malloc((unsigned)in_data_size); + oldsize = in_data_size; + } else if(in_data_size > oldsize) { + lzh_archive = realloc(lzh_archive, (unsigned)in_data_size); + oldsize = in_data_size; + } + if(lzh_archive == NULL) { + (void)fprintf(stderr, "Insufficient memory for archive.\n"); + exit(1); + } + if(fread(lzh_archive, 1, in_data_size, infp) != in_data_size) { + (void)fprintf(stderr, "Can't read archive.\n"); +#ifdef SCAN + do_error("macunpack: Can't read archive"); +#endif /* SCAN */ + exit(1); + } + lzh_pointer = lzh_archive; + while(1) { + if(in_data_size == 0) { + break; + } + if(lzh_filehdr(&filehdr) == 0) { + break; + } + m = lzh_checkm(&filehdr); + if(m < 0) { + (void)fprintf(stderr, + "Skipping file: \"%s\"; unknown method: %.5s.\n", + text, filehdr.method); + lzh_skip(&filehdr); + continue; + } + if(!write_it) { + /* We are skipping a folder. Skip the file if lzh_finfo is a + prefix of or identical to the folder info in the file. */ + if(lzh_fsize <= filehdr.extendsize && + !strncmp(lzh_finfo, filehdr.extend, lzh_fsize)) { + /* It was true, so we skip. */ + lzh_skip(&filehdr); + continue; + } + /* We have left the folder we were skipping. */ + } + /* Now we must leave folders until lzh_finfo is a proper prefix or + identical to the folder info in the file. */ + while(lzh_fsize > filehdr.extendsize || + strncmp(lzh_finfo, filehdr.extend, lzh_fsize)) { + /* Not a proper prefix, leave folder. First determine which! */ + i = lzh_fsize - 1; + while(--i >= 0 && lzh_finfo[i] != ':'); + i = i + 1; + transname(lzh_finfo + i, loc_name, lzh_fsize - i - 1); + lzh_fsize = i; + if(write_it) { + indent--; + if(!info_only) { + enddir(); + } + if(list) { + do_indent(indent); + (void)fprintf(stderr, "leaving folder \"%s\"\n", loc_name); + } + } + write_it = 1; + } + write_it = 1; + /* lzh_finfo is a proper prefix or identical, just show so. */ + lzh_finfo = filehdr.extend; + /* Now enter directories while lzh_finfo is smaller than extend. */ + while(lzh_fsize < filehdr.extendsize) { + i = lzh_fsize; + while(lzh_finfo[++i] != ':'); + transname(lzh_finfo + lzh_fsize, loc_name, i - lzh_fsize); + for(j = 0; j < INFOBYTES; j++) { + dirinfo[j] = 0; + } + dirinfo[I_NAMEOFF] = i - lzh_fsize; + copy(dirinfo + I_NAMEOFF + 1, lzh_finfo + lzh_fsize, i - lzh_fsize); + lzh_fsize = i + 1; + if(list) { + do_indent(indent); + (void)fprintf(stderr, "folder=\"%s\"", loc_name); + if(query) { + write_it = do_query(); + } else { + (void)fputc('\n', stderr); + } + if(write_it) { + indent++; + } + } + if(write_it && !info_only) { + do_mkdir(loc_name, dirinfo); + } + if(!write_it) { + break; + } + } + if(!write_it) { + lzh_skip(&filehdr); + } else { + lzh_wrfile(&filehdr, m); + } + } + /* Leaving some more directories! */ + while(lzh_fsize != 0) { + i = lzh_fsize - 1; + while(--i >= 0 && lzh_finfo[i] != ':'); + i = i + 1; + transname(lzh_finfo + i, loc_name, lzh_fsize - i - 1); + lzh_fsize = i; + if(write_it) { + } + if(write_it) { + indent--; + if(!info_only) { + enddir(); + } + if(list) { + do_indent(indent); + (void)fprintf(stderr, "leaving folder \"%s\"\n", loc_name); + } + } + } +} + +static int lzh_filehdr(f) +struct fileHdr *f; +{ + register int i; + char *hdr; + int c; + int ext_ptr; + int chk_sum = 0; + char *ptr; + + if(in_data_size <= 0) { + return 0; + } + for(i = 0; i < INFOBYTES; i++) { + info[i] = '\0'; + } + hdr = lzh_pointer; + in_data_size -= 2; + lzh_pointer += 2; + if(in_data_size < 0) { + in_data_size++; + } + f->hsize = (unsigned char)hdr[L_HSIZE]; + if(f->hsize == 0) { + return 0; + } + f->hcrc = (unsigned char)hdr[L_HCRC]; + ptr = hdr + L_METHOD; + in_data_size -= f->hsize; + lzh_pointer += f->hsize; + copy(&(f->method[0]), hdr + L_METHOD, 5); + f->psize = get4i(hdr + L_PSIZE); + f->upsize = get4i(hdr + L_UPSIZE); + f->lastmod = get4i(hdr + L_LASTMOD); + f->attribute = hdr[L_ATTRIBUTE + 1]; + if(f->attribute < 2) { + for(i = 0; i < f->hsize; i++) { + chk_sum += *ptr++; + } + chk_sum &= BYTEMASK; + if(chk_sum != f->hcrc) { + (void)fprintf(stderr, + "Header checksum error; got %.2x, must be %.2x.\n", + chk_sum, f->hcrc); +#ifdef SCAN + do_error("macunpack: Header checksum error"); +#endif /* SCAN */ + exit(1); + } + f->nlength = (unsigned char)hdr[L_NLENGTH]; + info[I_NAMEOFF] = f->nlength; + copy(info + I_NAMEOFF + 1, hdr + L_NAME, (int)f->nlength); + transname(hdr + L_NAME, text, (int)f->nlength); + ext_ptr = L_NLENGTH + f->nlength + 1; + f->crc = get2i(hdr + ext_ptr + L_CRC); + if(f->attribute == 1) { + f->etype = hdr[ext_ptr + L_ETYPE]; + f->extendsize = hdr[ext_ptr + L_EXTENDSZ]; + f->extend = hdr + ext_ptr + L_EXTEND; + } else { + f->extend = NULL; + f->extendsize = 0; + } + } else if(f->attribute == 2) { + in_data_size += 2; + lzh_pointer -= 2; + f->nlength = hdr[L_2EXTENDSZ] - 3; + info[I_NAMEOFF] = f->nlength; + copy(info + I_NAMEOFF + 1, hdr + L_2EXTEND + 2, (int)f->nlength); + transname(hdr + L_2EXTEND + 2, text, (int)f->nlength); + ext_ptr = + f->crc = get2i(hdr + L_2CRC); + f->etype = hdr[L_2ETYPE]; + ext_ptr = L_2EXTEND + 2 + f->nlength; + f->extendsize = hdr[ext_ptr + L_EEXTENDSZ]; + f->extend = hdr + ext_ptr + L_EEXTEND; + } else { + (void)fprintf(stderr, "Unknown file header format (%d).\n", + (int)f->attribute); +#ifdef SCAN + do_error("macunpack: Unknown file header format"); +#endif /* SCAN */ + exit(1); + } + if(f->extend != NULL) { + if(f->extendsize > 5) { + f->extend += 2; + hdr = f->extend; + f->extendsize -= 3; + for(i = 0; i < f->extendsize; i++) { + c = *hdr++; + if((c & BYTEMASK) == BYTEMASK) { + hdr[-1] = ':'; + c = ':'; + } + } + c = *hdr++; + if(c == 5) { + hdr += 5; + } + } else { + if(f->extendsize == 5) { + hdr = f->extend; + f->extend = NULL; + f->extendsize = 0; + hdr += 5; + } else { + hdr = f->extend; + f->extend = NULL; + f->extendsize = 0; + } + } + } else { + hdr = hdr + ext_ptr; + } + lzh_data = hdr; + if(f->attribute != 0) { + lzh_data++; + } + return 1; +} + +static int lzh_checkm(f) +struct fileHdr *f; +{ + int i, nummeth; + char *meth; + + meth = f->method; + nummeth = sizeof(methods) / sizeof(struct methodinfo); + for(i = 0; i < nummeth; i++) { + if(!strncmp(methods[i].name, meth, 5)) { + return methods[i].number; + } + } + return -1; +} + +static char *lzh_methname(n) +int n; +{ + if(n > sizeof(methods) / sizeof(struct methodinfo)) { + return NULL; + } + return methods[n].name; +} + +static void lzh_wrfile(filehdr, method) +struct fileHdr *filehdr; +int method; +{ + char ftype[5], fauth[5]; + int rsrcLength, dataLength; + int doit; + char *mname; + unsigned long crc; + + if(filehdr->upsize > lzh_filesize) { + if(lzh_filesize == 0) { + lzh_file = malloc((unsigned)filehdr->upsize); + } else { + lzh_file = realloc(lzh_file, (unsigned)filehdr->upsize); + } + if(lzh_file == NULL) { + (void)fprintf(stderr, "Insufficient memory to unpack file.\n"); + exit(1); + } + } + switch(method) { + case lz4: + lzh_nocomp((unsigned long)128); + break; +#ifdef UNTESTED + case lz5: + lzh_lzss1((unsigned long)128); + break; + case lzs: + lzh_lzss2((unsigned long)128); + break; +#endif /* UNTESTED */ + case lh0: + lzh_nocomp((unsigned long)128); + break; + case lh1: + lzh_lzah((unsigned long)128); + break; +#ifdef UNDEF + case lh2: + lzh_lh2((unsigned long)128); + break; + case lh3: + lzh_lh3((unsigned long)128); + break; +#endif /* UNDEF */ +#ifdef UNTESTED + case lh4: + lzh_lzh12((unsigned long)128); + break; +#endif /* UNTESTED */ + case lh5: + lzh_lzh13((unsigned long)128); + break; + default: + mname = lzh_methname(method); + if(mname != NULL) { + do_indent(indent); + (void)fprintf(stderr, + "\tSorry, packing method not yet implemented.\n"); + do_indent(indent); + (void)fprintf(stderr, "File = \"%s\"; ", text); + (void)fprintf(stderr, "method = %s, skipping file.\n", mname); + lzh_skip(filehdr); + return; + } + (void)fprintf(stderr, + "There is something very wrong with this program!\n"); +#ifdef SCAN + do_error("macunpack: program error"); +#endif /* SCAN */ + exit(1); + } + /* Checks whether everything is packed as MacBinary. */ + if(*lzh_file != 0 /* More checks possible here. */) { + do_indent(indent); + (void)fprintf(stderr, "File = \"%s\" ", text); + (void)fprintf(stderr, "not packed in MacBinary, skipping file.\n"); +#ifdef SCAN + do_error("macunpack: not MacBinary"); +#endif /* SCAN */ + lzh_skip(filehdr); + return; + } + copy(info, lzh_file, 128); + rsrcLength = get4(info + I_RLENOFF); + dataLength = get4(info + I_DLENOFF); + transname(info + I_TYPEOFF, ftype, 4); + transname(info + I_AUTHOFF, fauth, 4); + if(list) { + do_indent(indent); + (void)fprintf(stderr, + "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld", + text, ftype, fauth, (long)dataLength, (long)rsrcLength); + } + if(info_only) { + doit = 0; + } else { + doit = 1; + } + if(query) { + doit = do_query(); + } else if(list) { + (void)fputc('\n', stderr); + } + if(doit) { + define_name(text); + start_info(info, (unsigned long)rsrcLength, (unsigned long)dataLength); + } + switch(method) { + case lz4: + if(verbose) { + (void)fprintf(stderr, "\tNo Compression (%.5s)", filehdr->method); + } + if(doit) { + lzh_nocomp(filehdr->upsize); + } + break; +#ifdef UNTESTED + case lz5: + if(verbose) { + (void)fprintf(stderr, "\tLZSS (%.5s) compressed (%4.1f%%)", + filehdr->method, 100.0 * filehdr->psize / filehdr->upsize); + } + if(doit) { + lzh_lzss1(filehdr->upsize); + } + break; + case lzs: + if(verbose) { + (void)fprintf(stderr, "\tLZSS (%.5s) compressed (%4.1f%%)", + filehdr->method, 100.0 * filehdr->psize / filehdr->upsize); + } + if(doit) { + lzh_lzss2(filehdr->upsize); + } + break; +#endif /* UNTESTED */ + case lh0: + if(verbose) { + (void)fprintf(stderr, "\tNo Compression (%.5s)", filehdr->method); + } + if(doit) { + lzh_nocomp(filehdr->upsize); + } + break; + case lh1: + if(verbose) { + (void)fprintf(stderr, "\tLZAH (%.5s) compressed (%4.1f%%)", + filehdr->method, 100.0 * filehdr->psize / filehdr->upsize); + } + if(doit) { + lzh_lzah(filehdr->upsize); + } + break; +#ifdef UNDEF + case lh2: + if(verbose) { + (void)fprintf(stderr, "\tLZAH (%.5s) compressed (%4.1f%%)", + filehdr->method, 100.0 * filehdr->psize / filehdr->upsize); + } + if(doit) { + lzh_lh2(filehdr->upsize); + } + break; + case lh3: + if(verbose) { + (void)fprintf(stderr, "\tLZH (%.5s) compressed (%4.1f%%)", + filehdr->method, 100.0 * filehdr->psize / filehdr->upsize); + } + if(doit) { + lzh_lzh3(filehdr->upsize); + } + break; +#endif /* UNDEF */ +#ifdef UNTESTED + case lh4: + if(verbose) { + (void)fprintf(stderr, "\tLZH (%.5s) compressed (%4.1f%%)", + filehdr->method, 100.0 * filehdr->psize / filehdr->upsize); + } + if(doit) { + lzh_lzh12(filehdr->upsize); + } + break; +#endif /* UNTESTED */ + case lh5: + if(verbose) { + (void)fprintf(stderr, "\tLZH (%.5s) compressed (%4.1f%%)", + filehdr->method, 100.0 * filehdr->psize / filehdr->upsize); + } + if(doit) { + lzh_lzh13(filehdr->upsize); + } + } + if(doit) { + crc = (*updcrc)(INIT_CRC, lzh_file, filehdr->upsize); + if(filehdr->crc != crc) { + (void)fprintf(stderr, + "CRC error on file: need 0x%04x, got 0x%04x\n", + filehdr->crc, (int)crc); +#ifdef SCAN + do_error("macunpack: CRC error on file"); +#endif /* SCAN */ + exit(1); + } + start_data(); + copy(out_ptr, lzh_file + 128, (int)(filehdr->upsize - 128)); + } + if(verbose) { + (void)fprintf(stderr, ".\n"); + } + if(doit) { + end_file(); + } + lzh_skip(filehdr); +} + +static void lzh_skip(filehdr) +struct fileHdr *filehdr; +{ + lzh_pointer += filehdr->psize; + in_data_size -= filehdr->psize; +} + +/*---------------------------------------------------------------------------*/ +/* -lz4- and -lh0: No compression */ +/*---------------------------------------------------------------------------*/ +static void lzh_nocomp(obytes) +unsigned long obytes; +{ + copy(lzh_file, lzh_data, (int)obytes); +} + +#ifdef UNTESTED +/*---------------------------------------------------------------------------*/ +/* -lz5-: LZSS compression, variant 1 */ +/*---------------------------------------------------------------------------*/ +static void lzh_lzss1(obytes) +unsigned long obytes; +{ + int mask, ch, lzcnt, lzptr, ptr, count; + char *p = lzh_lzbuf; + int i, j; + + for(i = 0; i < 256; i++) { + for(j = 0; j < 13; j++) { + *p++ = i; + } + } + for(i = 0; i < 256; i++) { + *p++ = i; + } + for(i = 0; i < 256; i++) { + *p++ = 255 - i; + } + for(i = 0; i < 128; i++) { + *p++ = 0; + } + for(i = 0; i < 128; i++) { + *p++ = ' '; + } + + tmp_out_ptr = out_ptr; + out_ptr = lzh_file; + ptr = LZ5BUFFSIZE - LZ5LOOKAHEAD; + count = 0; + lzh_current = lzh_data; + while(obytes != 0) { + if(count == 0) { + mask = *lzh_current++ & BYTEMASK; + count = 8; + } + count--; + ch = *lzh_current++ & BYTEMASK; + if ((mask & 1) != 0) { + *out_ptr++ = ch; + lzh_lzbuf[ptr++] = ch; + ptr &= LZ5MASK; + obytes--; + } else { + lzcnt = *lzh_current++; + lzptr = (ch & 0x00ff) | ((lzcnt << 4) & 0x0f00); + lzcnt = (lzcnt & 0x000f) + 3; + obytes -= lzcnt; + do { + ch = lzh_lzbuf[lzptr++]; + lzh_lzbuf[ptr++] = ch; + *out_ptr++ = ch; + lzptr &= LZ5MASK; + ptr &= LZ5MASK; + } while (--lzcnt != 0) ; + } + mask >>= 1; + } + out_ptr = tmp_out_ptr; +} + +/*---------------------------------------------------------------------------*/ +/* -lzs-: LZSS compression, variant 2 */ +/*---------------------------------------------------------------------------*/ +static void lzh_lzss2(obytes) +unsigned long obytes; +{ + int ch, lzcnt, lzptr, ptr, i; + + tmp_out_ptr = out_ptr; + out_ptr = lzh_file; + ptr = LZSBUFFSIZE - LZSLOOKAHEAD; + for(i = 0; i < ptr; i++) { + lzh_lzbuf[i] = ' '; + } + for(i = ptr; i < LZSBUFFSIZE; i++) { + lzh_lzbuf[i] = 0; + } + bit_be_init_getbits(); + bit_be_filestart = lzh_data; + bit_be_inbytes = -1; + while(obytes != 0) { + if(bit_be_getbits(1) == 0) { + ch = bit_be_getbits(8); + *out_ptr++ = ch; + lzh_lzbuf[ptr++] = ch; + ptr &= LZSMASK; + obytes--; + } else { + lzptr = bit_be_getbits(11); + lzcnt = bit_be_getbits(4) + 3; + obytes -= lzcnt; + do { + ch = lzh_lzbuf[lzptr++]; + lzh_lzbuf[ptr++] = ch; + *out_ptr++ = ch; + lzptr &= LZSMASK; + ptr &= LZSMASK; + } while (--lzcnt != 0) ; + } + } + out_ptr = tmp_out_ptr; +} +#endif /* UNTESTED */ + +/*---------------------------------------------------------------------------*/ +/* -lh1-: LZ compression plus adaptive Huffman encoding */ +/*---------------------------------------------------------------------------*/ +static void lzh_lzah(obytes) +unsigned long obytes; +{ + lzh_current = lzh_data + 2; /* SKIPPING BLOCKSIZE! */ + tmp_out_ptr = out_ptr; + out_ptr = lzh_file; + lzah_getbyte = lzh_getbyte; + de_lzah(obytes); + out_ptr = tmp_out_ptr; +} + +static unsigned char lzh_getbyte() +{ + return *lzh_current++; +} + +#ifdef UNDEF +/*---------------------------------------------------------------------------*/ +/* -lh2-: LZ** compression */ +/*---------------------------------------------------------------------------*/ +static void lzh_lh2(obytes) +unsigned long obytes; +{ +} + +/*---------------------------------------------------------------------------*/ +/* -lh3-: LZ** compression */ +/*---------------------------------------------------------------------------*/ +static void lzh_lh3(obytes) +unsigned long obytes; +{ +} +#endif /* UNDEF */ + +#ifdef UNTESTED +/*---------------------------------------------------------------------------*/ +/* -lh4-: LZ(12) compression plus Huffman encoding */ +/*---------------------------------------------------------------------------*/ +static void lzh_lzh12(obytes) +unsigned long obytes; +{ + lzh_current = lzh_data; + tmp_out_ptr = out_ptr; + out_ptr = lzh_file; + /* Controlled by obytes only */ + de_lzh((long)(-1), (long)obytes, &lzh_current, 12); + out_ptr = tmp_out_ptr; +} +#endif /* UNTESTED */ + +/*---------------------------------------------------------------------------*/ +/* -lh5-: LZ(13) compression plus Huffman encoding */ +/*---------------------------------------------------------------------------*/ +static void lzh_lzh13(obytes) +unsigned long obytes; +{ + lzh_current = lzh_data; + tmp_out_ptr = out_ptr; + out_ptr = lzh_file; + /* Controlled by obytes only */ + de_lzh((long)(-1), (long)obytes, &lzh_current, 13); + out_ptr = tmp_out_ptr; +} +#else /* LZH */ +int lzh; /* keep lint and some compilers happy */ +#endif /* LZH */ + diff --git a/macunpack/lzh.h b/macunpack/lzh.h new file mode 100755 index 0000000..5ebf8e5 --- /dev/null +++ b/macunpack/lzh.h @@ -0,0 +1,67 @@ +#define FILEHDRSIZE 22 +#define TOTALSIZE 64 +#define L_HSIZE 0 +#define L_HCRC 1 +#define L_METHOD 2 +#define L_PSIZE 7 +#define L_UPSIZE 11 +#define L_LASTMOD 15 +#define L_ATTRIBUTE 19 + +/* Level 0 and level 1 headers */ +#define L_NLENGTH 21 +#define L_NAME 22 +/* Offset after name */ +#define L_CRC 0 +#define L_ETYPE 2 +#define L_EXTENDSZ 3 +#define L_EXTEND 4 + +/* Level 2 header */ +#define L_2CRC 21 +#define L_2ETYPE 23 +#define L_2EXTENDSZ 24 +#define L_2EXTEND 25 + +/* Extension definition, EXTEND defines the size of the extension. */ +#define L_KIND 0 /* After EXTEND */ +#define L_ENAME 2 /* Extension name, EXTEND-3 bytes long */ +/* Offset after name */ +#define L_EEXTENDSZ 0 +#define L_EEXTEND 1 + +typedef struct fileHdr { /* 58 bytes */ + unsigned char hsize; + unsigned char hcrc; + char method[5]; + unsigned long psize; + unsigned long upsize; + unsigned long lastmod; + unsigned short attribute; + unsigned char nlength; + char name[32]; + unsigned short crc; + unsigned char etype; + unsigned char extendsize; + char *extend; + char *data; +}; + +/* Currently known methods: */ +#define lh0 0 +#define lh1 1 +#define lh2 2 +#define lh3 3 +#define lh4 4 +#define lh5 5 +#define lz4 6 +#define lz5 7 +#define lzs 8 + +extern char *lzh_pointer; +extern char *lzh_data; +extern char *lzh_finfo; +extern int lzh_fsize; +extern int lzh_kind; +extern char *lzh_file; + diff --git a/macunpack/macbinary.c b/macunpack/macbinary.c new file mode 100755 index 0000000..cab1e36 --- /dev/null +++ b/macunpack/macbinary.c @@ -0,0 +1,555 @@ +#include "macunpack.h" +#include "globals.h" +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "../fileio/kind.h" +#include "zmahdr.h" +#include "../util/util.h" + +extern void dir(); +extern void mcb(); +#ifdef BIN +extern void bin(); +#endif /* BIN */ +#ifdef JDW +extern void jdw(); +#endif /* JDW */ +#ifdef STF +extern void stf(); +#endif /* STF */ +#ifdef LZC +extern void lzc(); +#endif /* LZC */ +#ifdef ASQ +extern void asq(); +#endif /* ASQ */ +#ifdef ARC +extern void arc(); +#endif /* ARC */ +#ifdef PIT +extern void pit(); +#endif /* PIT */ +#ifdef SIT +extern void sit(); +#endif /* SIT */ +#ifdef DIA +extern void dia(); +#endif /* DIA */ +#ifdef CPT +extern void cpt(); +#endif /* CPT */ +#ifdef ZMA +extern void zma(); +#endif /* ZMA */ +#ifdef LZH +extern void lzh(); +#endif /* LZH */ +#ifdef DD +extern void dd_file(); +extern void dd_arch(); +#endif /* DD */ + +static void skip_file(); +#ifdef SCAN +static void get_idf(); +#endif /* SCAN */ + +#define Z (ZMAHDRS2 + 1) + +static int info_given; + +void macbinary() +{ + char header[INFOBYTES]; + int c; + + while(1) { + if((c = fgetc(infp)) == EOF) { + break; + } + (void)ungetc(c, infp); + if(fread(header, 1, Z, infp) != Z) { + (void)fprintf(stderr, "Can't read MacBinary header.\n"); +#ifdef SCAN + do_error("macunpack: Can't read MacBinary header"); +#endif /* SCAN */ + exit(1); + } +#ifdef ZMA + if(!strncmp(header + 1, ZMAHDR, ZMAHDRS2)) { + /* Can distinguish zoom data forks only this way from macbinary */ + if(verbose) { + (void)fprintf(stderr, "This is a \"Zoom\" archive.\n"); + } + zma(header, (unsigned long)0); + exit(0); + } +#endif /* ZMA */ + if(fread(header + Z, 1, INFOBYTES - Z, infp) != INFOBYTES - Z) { + (void)fprintf(stderr, "Can't read MacBinary header.\n"); +#ifdef SCAN + do_error("macunpack: Can't read MacBinary header"); +#endif /* SCAN */ + exit(1); + } + if(verbose && !info_given) { + do_indent(indent); + (void)fprintf(stderr, "This is \"MacBinary\" input.\n"); + info_given = 1; + } + if(header[I_NAMEOFF] & 0x80) { + dir(header); + continue; + } + in_data_size = get4(header + I_DLENOFF); + in_rsrc_size = get4(header + I_RLENOFF); + in_ds = (((in_data_size + 127) >> 7) << 7); + in_rs = (((in_rsrc_size + 127) >> 7) << 7); + ds_skip = in_ds - in_data_size; + rs_skip = in_rs - in_rsrc_size; + if(dir_skip != 0) { + skip_file(in_ds + in_rs); + continue; + } +#ifdef SCAN + if(header[I_NAMEOFF] == 0) { + get_idf((int)header[I_NAMEOFF + 1]); + skip_file(ds_skip + in_rs); + continue; + } +#endif /* SCAN */ + header[I_NAMEOFF + 1 + header[I_NAMEOFF]] = 0; +#ifdef BIN + if(!strncmp(header + I_TYPEOFF, "TEXT", 4) && + !strncmp(header + I_AUTHOFF, "BnHq", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, + "This is a \"BinHex 5.0\" packed file.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, PACK_NAME); +#endif /* SCAN */ + bin(header, in_data_size, 0); + skip_file(ds_skip + in_rs); + continue; + } + if(!strncmp(header + I_TYPEOFF, "TEXT", 4) && + !strncmp(header + I_AUTHOFF, "GJBU", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, + "This is a \"MacBinary 1.0\" packed file.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, PACK_NAME); +#endif /* SCAN */ + bin(header, in_data_size, 0); + skip_file(ds_skip + in_rs); + continue; + } + /* Recognize only if creator is UMcp. UMCP uses ttxt as default. */ + if(!strncmp(header + I_TYPEOFF, "TEXT", 4) && + !strncmp(header + I_AUTHOFF, "UMcp", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, "This is a \"UMCP\" packed file.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, PACK_NAME); +#endif /* SCAN */ + bin(header, in_data_size, 1); + skip_file(ds_skip + in_rs); + continue; + } +#endif /* BIN */ +#ifdef JDW + if(!strncmp(header + I_TYPEOFF, "Smal", 4) && + !strncmp(header + I_AUTHOFF, "Jdw ", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, + "This is a \"Compress It\" compressed file.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, PACK_NAME); +#endif /* SCAN */ + jdw((unsigned long)in_data_size); + skip_file(ds_skip + in_rs); + continue; + } +#endif /* JDW */ +#ifdef STF + if(!strncmp(header + I_TYPEOFF, "COMP", 4) && + !strncmp(header + I_AUTHOFF, "STF ", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, + "This is a \"ShrinkToFit\" compressed file.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, PACK_NAME); +#endif /* SCAN */ + stf((unsigned long)in_data_size); + skip_file(ds_skip + in_rs); + continue; + } +#endif /* STF */ +#ifdef LZC + if(!strncmp(header + I_TYPEOFF, "ZIVM", 4) && + !strncmp(header + I_AUTHOFF, "LZIV", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, + "This is a \"MacCompress(M)\" compressed file.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, PACK_NAME); +#endif /* SCAN */ + lzc(header); + skip_file(ds_skip + in_rs); + continue; + } + if(!strncmp(header + I_TYPEOFF, "ZIVU", 4) && + !strncmp(header + I_AUTHOFF, "LZIV", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, + "This is a \"MacCompress(U)\" compressed file.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, PACK_NAME); +#endif /* SCAN */ + lzc(header); + continue; + } +#endif /* LZC */ +#ifdef ASQ + if(!strncmp(header + I_TYPEOFF, "ArCv", 4) && + !strncmp(header + I_AUTHOFF, "TrAS", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, + "This is a \"AutoSqueeze\" compressed file.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, PACK_NAME); +#endif /* SCAN */ + lzh(0); + skip_file(ds_skip + in_rs); + continue; + } +#endif /* ASQ */ +#ifdef ARC + if(!strncmp(header + I_TYPEOFF, "mArc", 4) && + !strncmp(header + I_AUTHOFF, "arc*", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, "This is a \"ArcMac\" archive.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, ARCH_NAME); +#endif /* SCAN */ + arc(); + skip_file(ds_skip + in_rs); + continue; + } + if(!strncmp(header + I_TYPEOFF, "APPL", 4) && + !strncmp(header + I_AUTHOFF, "arc@", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, + "This is a \"ArcMac\" self extracting archive.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, ARCH_NAME); +#endif /* SCAN */ + arc(); + skip_file(ds_skip + in_rs); + continue; + } +#endif /* ARC */ +#ifdef PIT + if(!strncmp(header + I_TYPEOFF, "PIT ", 4) && + !strncmp(header + I_AUTHOFF, "PIT ", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, "This is a \"PackIt\" archive.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, ARCH_NAME); +#endif /* SCAN */ + pit(); + skip_file(ds_skip + in_rs); + continue; + } +#endif /* PIT */ +#ifdef SIT + if(!strncmp(header + I_TYPEOFF, "SIT!", 4) && + !strncmp(header + I_AUTHOFF, "SIT!", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, "This is a \"StuffIt\" archive.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, ARCH_NAME); +#endif /* SCAN */ + sit(); + skip_file(ds_skip + in_rs); + continue; + } + if(!strncmp(header + I_TYPEOFF, "SITD", 4) && + !strncmp(header + I_AUTHOFF, "SIT!", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, + "This is a \"StuffIt Deluxe\" archive.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, ARCH_NAME); +#endif /* SCAN */ + sit(); + skip_file(ds_skip + in_rs); + continue; + } + if(!strncmp(header + I_TYPEOFF, "APPL", 4) && + !strncmp(header + I_AUTHOFF, "aust", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, + "This is a \"StuffIt\" self extracting archive.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, ARCH_NAME); +#endif /* SCAN */ + sit(); + skip_file(ds_skip + in_rs); + continue; + } +#endif /* SIT */ +#ifdef DIA + if(!strncmp(header + I_TYPEOFF, "Pack", 4) && + !strncmp(header + I_AUTHOFF, "Pack", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, "This is a \"Diamond\" archive.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, ARCH_NAME); +#endif /* SCAN */ + dia((unsigned char *)header); + skip_file(ds_skip + in_rs); + continue; + } + if(!strncmp(header + I_TYPEOFF, "APPL", 4) && + !strncmp(header + I_AUTHOFF, "Pack", 4) && + in_data_size != 0) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, + "This is a \"Diamond\" self extracting archive.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, ARCH_NAME); +#endif /* SCAN */ + dia((unsigned char *)header); + skip_file(ds_skip + in_rs); + continue; + } +#endif /* DIA */ +#ifdef CPT + if(!strncmp(header + I_TYPEOFF, "PACT", 4) && + !strncmp(header + I_AUTHOFF, "CPCT", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, "This is a \"Compactor\" archive.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, ARCH_NAME); +#endif /* SCAN */ + cpt(); + skip_file(ds_skip + in_rs); + continue; + } + if(!strncmp(header + I_TYPEOFF, "APPL", 4) && + !strncmp(header + I_AUTHOFF, "EXTR", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, + "This is a \"Compactor\" self extracting archive.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, ARCH_NAME); +#endif /* SCAN */ + cpt(); + skip_file(ds_skip + in_rs); + continue; + } +#endif /* CPT */ +#ifdef ZMA + if(!strncmp(header + I_TYPEOFF, "zooM", 4) && + !strncmp(header + I_AUTHOFF, "zooM", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, "This is a \"Zoom\" archive.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, ARCH_NAME); +#endif /* SCAN */ + zma((char *)NULL, (unsigned long)in_data_size); + skip_file(ds_skip + in_rs); + continue; + } + if(!strncmp(header + I_TYPEOFF, "APPL", 4) && + !strncmp(header + I_AUTHOFF, "Mooz", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, + "This is a \"Zoom\" self extracting archive.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, ARCH_NAME); +#endif /* SCAN */ + zma((char *)NULL, (unsigned long)in_data_size); + skip_file(ds_skip + in_rs); + continue; + } +#endif /* ZMA */ +#ifdef LZH + if(!strncmp(header + I_TYPEOFF, "LARC", 4) && + !strncmp(header + I_AUTHOFF, "LARC", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, + "This is a \"MacLHa (LHARC)\" archive.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, ARCH_NAME); +#endif /* SCAN */ + lzh(0); + skip_file(ds_skip + in_rs); + continue; + } + if(!strncmp(header + I_TYPEOFF, "LHA ", 4) && + !strncmp(header + I_AUTHOFF, "LARC", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, + "This is a \"MacLHa (LHA)\" archive.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, ARCH_NAME); +#endif /* SCAN */ + lzh(1); + skip_file(ds_skip + in_rs); + continue; + } +#endif /* LZH */ +#ifdef DD + if((!strncmp(header + I_TYPEOFF, "DD01", 4) || + !strncmp(header + I_TYPEOFF, "DDF?", 3) || + !strncmp(header + I_TYPEOFF, "DDf?", 3)) && + !strncmp(header + I_AUTHOFF, "DDAP", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, + "This is a \"DiskDoubler\" compressed file.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, PACK_NAME); +#endif /* SCAN */ + dd_file((unsigned char *)header); + skip_file(ds_skip + in_rs); + continue; + } + if(!strncmp(header + I_TYPEOFF, "DDAR", 4) && + !strncmp(header + I_AUTHOFF, "DDAP", 4)) { + if(verbose) { + do_indent(indent); + (void)fprintf(stderr, "This is a \"DiskDoubler\" archive.\n"); + } +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, ARCH_NAME); +#endif /* SCAN */ + dd_arch((unsigned char *)header); + skip_file(ds_skip + in_rs); + continue; + } + if(!strncmp(header + I_TYPEOFF, "APPL", 4) && + !strncmp(header + I_AUTHOFF, "DSEA", 4)) { + if(verbose) { + do_indent(indent); + } + c = getc(infp); + (void)ungetc(c, infp); + if(c == 'D') { + if(verbose) { + (void)fprintf(stderr, + "This is a \"DiskDoubler\" self extracting archive.\n"); +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, ARCH_NAME); +#endif /* SCAN */ + } + dd_arch((unsigned char *)header); + } else { + if(verbose) { + (void)fprintf(stderr, + "This is a \"DiskDoubler\" self decompressing file.\n"); +#ifdef SCAN + do_idf(header + I_NAMEOFF + 1, PACK_NAME); +#endif /* SCAN */ + } + dd_file((unsigned char *)header); + } + skip_file(ds_skip + in_rs); + continue; + } +#endif /* DD */ + if(header[0] == 0 /* MORE CHECKS HERE! */) { + mcb(header, (unsigned long)in_rsrc_size, + (unsigned long)in_data_size, in_ds + in_rs); + continue; + } else { + (void)fprintf(stderr, "Unrecognized archive type.\n"); + exit(1); + } + } +} + +static void skip_file(skip) +int skip; +{ + char buff[1024]; + int n; + + while(skip > 0) { + n = (skip < 1024 ? skip : 1024); + if(fread(buff, 1, n, infp) != n) { + (void)fprintf(stderr, "Incomplete file.\n"); +#ifdef SCAN + do_error("macunpack: Incomplete file"); +#endif /* SCAN */ + exit(1); + } + skip -= n; + } +} + +#ifdef SCAN +static void get_idf(kind) +int kind; +{ + char filename[255]; + + if(fread(filename, 1, in_data_size, infp) != in_data_size) { + (void)fprintf(stderr, "Incomplete file.\n"); +#ifdef SCAN + do_error("macunpack: Incomplete file"); +#endif /* SCAN */ + exit(1); + } + filename[in_data_size] = 0; + do_idf(filename, kind); +} +#endif /* SCAN */ + diff --git a/macunpack/macbinary.o b/macunpack/macbinary.o new file mode 100644 index 0000000..96680a4 Binary files /dev/null and b/macunpack/macbinary.o differ diff --git a/macunpack/macunpack.c b/macunpack/macunpack.c new file mode 100755 index 0000000..767512f --- /dev/null +++ b/macunpack/macunpack.c @@ -0,0 +1,201 @@ +#include "macunpack.h" +#include "globals.h" +#include "../util/patchlevel.h" +#include "../fileio/wrfile.h" +#include "../fileio/wrfileopt.h" +#include "../fileio/kind.h" +#include "../util/util.h" + +#define LOCALOPT "ilvqVH" + +extern char *strcat(); +#ifdef STF +extern void stf(); +#endif /* STF */ +#ifdef PIT +extern void pit(); +#endif /* PIT */ +#ifdef SIT +extern void sit(); +#endif /* SIT */ +#ifdef CPT +extern void cpt(); +#endif /* CPT */ +void macbinary(); + +static void usage(); + +static char options[128]; + +int main(argc, argv) +int argc; +char *argv[]; +{ + int c; + extern int optind; + extern char *optarg; + int errflg; + + set_wrfileopt(0); + (void)strcat(options, get_wrfileopt()); + (void)strcat(options, LOCALOPT); + errflg = 0; + + while((c = getopt(argc, argv, options)) != EOF) { +#ifdef SCAN + if(c == 'S') { + no_dd++; + } +#endif /* SCAN */ + if(!wrfileopt((char)c)) { + switch(c) { + case 'l': + list++; + break; + case 'q': + query++; + break; + case 'v': + verbose++; + break; + case 'i': + info_only++; + break; + case '?': + errflg++; + break; + case 'H': + give_wrfileopt(); + (void)fprintf(stderr, "Macunpack specific options:\n"); + (void)fprintf(stderr, + "-i:\tgive information only, do not unpack\n"); + (void)fprintf(stderr, "-l:\tgive listing\n"); + (void)fprintf(stderr, "-v:\tgive verbose listing\n"); + (void)fprintf(stderr, + "-q:\tquery for every file/folder before unpacking\n"); + (void)fprintf(stderr, + "-V:\tgive information about this version\n"); + (void)fprintf(stderr, "-H:\tthis message\n"); + (void)fprintf(stderr, "Default is silent unpacking\n"); + exit(0); + case 'V': + (void)fprintf(stderr, "Version %s, ", VERSION); + (void)fprintf(stderr, "patchlevel %d", PATCHLEVEL); + (void)fprintf(stderr, "%s.\n", get_mina()); + (void)fprintf(stderr, "Archive/file types recognized:\n"); +#ifdef BIN + (void)fprintf(stderr, + "\tBinHex 5.0, MacBinary 1.0 and UMCP (with caveat)\n"); +#endif /* BIN */ +#ifdef JDW + (void)fprintf(stderr, "\tCompress It\n"); +#endif /* JDW */ +#ifdef STF + (void)fprintf(stderr, "\tShrinkToFit\n"); +#endif /* STF */ +#ifdef LZC + (void)fprintf(stderr, "\tMacCompress\n"); +#endif /* LZC */ +#ifdef ASQ + (void)fprintf(stderr, "\tAutoSqueeze\n"); +#endif /* ASQ */ +#ifdef ARC + (void)fprintf(stderr, "\tArcMac\n"); +#endif /* ARC */ +#ifdef PIT + (void)fprintf(stderr, "\tPackIt\n"); +#endif /* PIT */ +#ifdef SIT + (void)fprintf(stderr, "\tStuffIt and StuffIt Deluxe\n"); +#endif /* SIT */ +#ifdef DIA + (void)fprintf(stderr, "\tDiamond\n"); +#endif /* DIA */ +#ifdef CPT + (void)fprintf(stderr, "\tCompactor\n"); +#endif /* CPT */ +#ifdef ZMA + (void)fprintf(stderr, "\tZoom\n"); +#endif /* ZMA */ +#ifdef LZH + (void)fprintf(stderr, "\tMacLHa\n"); +#endif /* LZH */ +#ifdef DD + (void)fprintf(stderr, "\tDiskDoubler and AutoDoubler\n"); +#endif /* DD */ + exit(0); + } + } + } + if(errflg) { + usage(); + exit(1); + } + + if(optind == argc) { + infp = stdin; + } else { + if((infp = fopen(argv[optind], "r")) == NULL) { + (void)fprintf(stderr,"Can't open input file \"%s\"\n",argv[optind]); + exit(1); + } +#ifdef SCAN + do_idf(argv[optind], UNIX_NAME); +#endif /* SCAN */ + } + + if(info_only || verbose || query) { + list++; + } + c = getc(infp); + (void)ungetc(c, infp); + switch(c) { + case 0: + macbinary(); + break; +#ifdef STF + case 'R': + if(verbose) { + (void)fprintf(stderr, "This is a \"ShrinkToFit\" packed file.\n"); + } + stf(~(unsigned long)1); + break; +#endif /* STF */ +#ifdef PIT + case 'P': + if(verbose) { + (void)fprintf(stderr, "This is a \"PackIt\" archive.\n"); + } + pit(); + break; +#endif /* PIT */ +#ifdef SIT + case 'S': + if(verbose) { + (void)fprintf(stderr, "This is a \"StuffIt\" archive.\n"); + } + sit(); + break; +#endif /* SIT */ +#ifdef CPT + case 1: + if(verbose) { + (void)fprintf(stderr, "This is a \"Compactor\" archive.\n"); + } + cpt(); + break; +#endif /* CPT */ + default: + (void)fprintf(stderr, "Unrecognized archive type\n"); + exit(1); + } + exit(0); + /* NOTREACHED */ +} + +static void usage() +{ + (void)fprintf(stderr, "Usage: macunpack [-%s] [filename]\n", options); + (void)fprintf(stderr, "Use \"macunpack -H\" for help.\n"); +} + diff --git a/macunpack/macunpack.h b/macunpack/macunpack.h new file mode 100755 index 0000000..2c9cb2a --- /dev/null +++ b/macunpack/macunpack.h @@ -0,0 +1,15 @@ +#define UNTESTED /* Know about the untested algorithms */ +#define BIN /* Know about BinHex 5.0 etc. */ +#define JDW /* Know about Compress It */ +#define STF /* Know about ShrinkToFit */ +#define LZC /* Know about MacCompress */ +#undef ASQ /* Know about AutoSqueeze */ +#undef ARC /* Know about ArcMac */ +#define PIT /* Know about PackIt */ +#define SIT /* Know about StuffIt */ +#define DIA /* Know about Diamond */ +#define CPT /* Know about Compactor */ +#define ZMA /* Know about Zoom */ +#define LZH /* Know about LHa */ +#define DD /* Know about DiskDoubler */ + diff --git a/macunpack/macunpack.o b/macunpack/macunpack.o new file mode 100644 index 0000000..ef4770d Binary files /dev/null and b/macunpack/macunpack.o differ diff --git a/macunpack/makefile b/macunpack/makefile new file mode 100755 index 0000000..69a19d3 --- /dev/null +++ b/macunpack/makefile @@ -0,0 +1,230 @@ +CFLAGS = -O $(CF) + +SRCS = macunpack.c \ + globals.c \ + macbinary.c \ + dir.c \ + mcb.c \ + bin.c \ + jdw.c \ + stf.c \ + lzc.c \ + pit.c \ + sit.c \ + dia.c \ + cpt.c \ + zma.c \ + lzh.c \ + dd.c \ + de_huffman.c \ + de_compress.c \ + de_lzah.c \ + de_lzh.c \ + crc.c \ + bits_be.c + +OBJS = macunpack.o \ + globals.o \ + macbinary.o \ + dir.o \ + mcb.o \ + bin.o \ + jdw.o \ + stf.o \ + lzc.o \ + pit.o \ + sit.o \ + dia.o \ + cpt.o \ + zma.o \ + lzh.o \ + dd.o \ + de_huffman.o \ + de_compress.o \ + de_lzah.o \ + de_lzh.o \ + crc.o \ + bits_be.o + +LIB = ../crc/libcrc.a +TNAME = ../util/transname +UNAME = ../util/util +ONAME = ../fileio/wrfile +GNAME = ../fileio/fileglob +XOBJS = $(TNAME).o $(UNAME).o $(ONAME).o $(GNAME).o +XSRCS = $(TNAME).c $(UNAME).c $(ONAME).c $(GNAME).c +CRCS = ../crc/arc.c ../crc/binhex.c ../crc/zip.c + +macunpack: $(OBJS) $(LIB) $(XOBJS) + $(CC) $(CFLAGS) -o macunpack $(OBJS) $(XOBJS) $(LIB) + +$(LIB): ../crc/makecrc.c + (cd ../crc; make CC=$(CC) CF="$(CF)" ) + +$(TNAME).o: $(TNAME).c + (cd ../util; make CC=$(CC) CF="$(CF)" ) + +$(UNAME).o: $(UNAME).c + (cd ../util; make CC=$(CC) CF="$(CF)" ) + +$(ONAME).o: $(ONAME).c + (cd ../fileio; make CC=$(CC) CF="$(CF)" ) + +$(GNAME).o: $(GNAME).c + (cd ../fileio; make CC=$(CC) CF="$(CF)" ) + +lint: + lint $(CF) $(LFLAGS) $(SRCS) $(XSRCS) $(CRCS) + +clean: + -rm -f *.o + +clobber:clean + -rm -f macunpack + +macunpack.o: macunpack.h +macunpack.o: globals.h +macunpack.o: ../util/patchlevel.h +macunpack.o: ../fileio/wrfile.h +macunpack.o: ../fileio/wrfileopt.h +macunpack.o: ../fileio/kind.h +macunpack.o: ../util/util.h +globals.o: globals.h +globals.o: ../fileio/machdr.h +globals.o: ../fileio/wrfile.h +globals.o: ../fileio/kind.h +macbinary.o: macunpack.h +macbinary.o: globals.h +macbinary.o: zmahdr.h +macbinary.o: ../fileio/machdr.h +macbinary.o: ../fileio/wrfile.h +macbinary.o: ../fileio/kind.h +macbinary.o: ../util/util.h +dir.o: globals.h +dir.o: ../fileio/machdr.h +dir.o: ../fileio/wrfile.h +dir.o: ../util/util.h +dir.o: ../util/masks.h +mcb.o: globals.h +mcb.o: ../fileio/machdr.h +mcb.o: ../fileio/wrfile.h +mcb.o: ../util/masks.h +mcb.o: ../util/util.h +bin.o: macunpack.h +bin.o: globals.h +bin.o: ../fileio/machdr.h +bin.o: ../fileio/wrfile.h +bin.o: ../fileio/kind.h +bin.o: ../util/util.h +bin.o: ../util/masks.h +jdw.o: macunpack.h +jdw.o: jdw.h +jdw.o: globals.h +jdw.o: huffman.h +jdw.o: ../fileio/wrfile.h +jdw.o: ../fileio/machdr.h +jdw.o: ../util/util.h +jdw.o: ../util/masks.h +stf.o: macunpack.h +stf.o: stf.h +stf.o: globals.h +stf.o: huffman.h +stf.o: ../util/curtime.h +stf.o: ../fileio/wrfile.h +stf.o: ../fileio/machdr.h +stf.o: ../util/util.h +lzc.o: macunpack.h +lzc.o: globals.h +lzc.o: lzc.h +lzc.o: ../util/util.h +lzc.o: ../fileio/machdr.h +lzc.o: ../fileio/wrfile.h +lzc.o: ../util/masks.h +pit.o: macunpack.h +pit.o: ../fileio/fileglob.h +pit.o: ../fileio/wrfile.h +pit.o: ../fileio/kind.h +pit.o: globals.h +pit.o: pit.h +pit.o: ../fileio/machdr.h +pit.o: crc.h +pit.o: ../util/masks.h +pit.o: ../util/util.h +pit.o: huffman.h +sit.o: macunpack.h +sit.o: globals.h +sit.o: sit.h +sit.o: crc.h +sit.o: ../util/util.h +sit.o: ../fileio/machdr.h +sit.o: ../fileio/wrfile.h +sit.o: ../fileio/kind.h +sit.o: ../util/masks.h +sit.o: huffman.h +dia.o: macunpack.h +dia.o: globals.h +dia.o: dia.h +dia.o: ../util/curtime.h +dia.o: ../util/masks.h +dia.o: ../fileio/machdr.h +dia.o: ../fileio/wrfile.h +dia.o: ../fileio/kind.h +dia.o: ../util/util.h +cpt.o: macunpack.h +cpt.o: globals.h +cpt.o: cpt.h +cpt.o: crc.h +cpt.o: ../util/util.h +cpt.o: ../fileio/machdr.h +cpt.o: ../fileio/wrfile.h +cpt.o: ../fileio/kind.h +cpt.o: ../util/masks.h +cpt.o: huffman.h +zma.o: macunpack.h +zma.o: globals.h +zma.o: zma.h +zma.o: crc.h +zma.o: ../fileio/machdr.h +zma.o: ../fileio/wrfile.h +zma.o: ../fileio/kind.h +zma.o: ../util/masks.h +zma.o: ../util/util.h +lzh.o: macunpack.h +lzh.o: globals.h +lzh.o: lzh.h +lzh.o: crc.h +lzh.o: ../fileio/wrfile.h +lzh.o: ../fileio/machdr.h +lzh.o: ../util/masks.h +lzh.o: ../util/util.h +lzh.o: bits_be.h +dd.o: macunpack.h +dd.o: globals.h +dd.o: dd.h +dd.o: crc.h +dd.o: ../fileio/machdr.h +dd.o: ../fileio/wrfile.h +dd.o: ../fileio/fileglob.h +dd.o: ../util/masks.h +dd.o: ../util/util.h +de_huffman.o: macunpack.h +de_huffman.o: globals.h +de_huffman.o: ../util/masks.h +de_huffman.o: huffman.h +de_huffman.o: ../fileio/wrfile.h +de_huffman.o: ../util/util.h +de_compress.o: macunpack.h +de_compress.o: globals.h +de_compress.o: ../fileio/wrfile.h +de_lzah.o: macunpack.h +de_lzah.o: globals.h +de_lzah.o: ../util/masks.h +de_lzah.o: ../fileio/wrfile.h +de_lzh.o: macunpack.h +de_lzh.o: globals.h +de_lzh.o: ../util/masks.h +de_lzh.o: ../fileio/wrfile.h +de_lzh.o: bits_be.h +bits_be.o: ../util/masks.h +bits_be.o: bits_be.h + diff --git a/macunpack/mcb.c b/macunpack/mcb.c new file mode 100755 index 0000000..e025498 --- /dev/null +++ b/macunpack/mcb.c @@ -0,0 +1,137 @@ +#include "globals.h" +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "../util/masks.h" +#include "../util/util.h" + +static int mcb_read; + +static void mcb_wrfile(); + +void mcb(hdr, rsrcLength, dataLength, toread) +char *hdr; +unsigned long rsrcLength, dataLength; +int toread; +{ + register int i; + int n; + char ftype[5], fauth[5]; + + mcb_read = toread; + for(i = 0; i < INFOBYTES; i++) { + info[i] = hdr[i]; + } + + n = hdr[I_NAMEOFF] & BYTEMASK; + if(n > F_NAMELEN) { + n = F_NAMELEN; + } + info[I_NAMEOFF] = n; + transname(hdr + I_NAMEOFF + 1, text, n); + if(hdr[I_LOCKOFF] & 1) { + hdr[I_FLAGOFF + 1] = PROTCT_MASK; + hdr[I_LOCKOFF] &= ~1; + } + + write_it = 1; + if(list) { + transname(hdr + I_TYPEOFF, ftype, 4); + transname(hdr + I_AUTHOFF, fauth, 4); + do_indent(indent); + (void)fprintf(stderr, + "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld", + text, ftype, fauth, (long)dataLength, (long)rsrcLength); + if(info_only) { + write_it = 0; + } + if(query) { + write_it = do_query(); + } else { + (void)fputc('\n', stderr); + } + } + + if(write_it) { + define_name(text); + } + if(write_it) { + start_info(info, rsrcLength, dataLength); + } + if(verbose) { + (void)fprintf(stderr, "\tData: "); + } + if(write_it) { + start_data(); + } + mcb_wrfile(dataLength); + if(verbose) { + (void)fprintf(stderr, ", Rsrc: "); + } + if(write_it) { + start_rsrc(); + } + mcb_wrfile(rsrcLength); + if(write_it) { + end_file(); + } + if(verbose) { + (void)fprintf(stderr, ".\n"); + } +} + +static void mcb_wrfile(ibytes) +unsigned long ibytes; +{ + int n; + + if(ibytes == 0) { + if(verbose) { + (void)fprintf(stderr, "empty"); + } + return; + } + if(verbose) { + (void)fprintf(stderr, "No compression"); + } + if(write_it) { + n = fread(out_buffer, 1, (int)ibytes, infp); + if(n != ibytes) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("macunpack: Premature EOF"); +#endif /* SCAN */ + exit(1); + } + mcb_read -= n; + n = ((n + 127) / 128) * 128 - n; + if(n > mcb_read) { + n = mcb_read; + } + mcb_read -= n; + while(n-- > 0) { + if(getc(infp) == EOF) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("macunpack: Premature EOF"); +#endif /* SCAN */ + exit(1); + } + } + } else { + n = ((ibytes + 127) / 128) * 128; + if(n > mcb_read) { + n = mcb_read; + } + mcb_read -= n; + while(n-- > 0) { + if(getc(infp) == EOF) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("macunpack: Premature EOF"); +#endif /* SCAN */ + exit(1); + } + } + } +} + diff --git a/macunpack/mcb.o b/macunpack/mcb.o new file mode 100644 index 0000000..24ec931 Binary files /dev/null and b/macunpack/mcb.o differ diff --git a/macunpack/pit.c b/macunpack/pit.c new file mode 100755 index 0000000..9c5eae2 --- /dev/null +++ b/macunpack/pit.c @@ -0,0 +1,285 @@ +#include "macunpack.h" +#ifdef PIT +#include "../fileio/wrfile.h" +#include "../fileio/fileglob.h" +#include "../fileio/kind.h" +#include "globals.h" +#include "pit.h" +#include "../fileio/machdr.h" +#include "crc.h" +#include "../util/masks.h" +#include "../util/util.h" +#include "huffman.h" + +extern void read_tree(); +extern void de_huffman(); +extern void set_huffman(); + +static int pit_filehdr(); +static void pit_wrfile(); +static void pit_nocomp(); +static void pit_huffman(); + +void pit() +{ + struct pit_header filehdr; + char pithdr[4]; + int decode, synced, ch; + unsigned long data_crc, crc; + + updcrc = binhex_updcrc; + crcinit = binhex_crcinit; + set_huffman(HUFF_BE); + synced = 0; + while(1) { + if(!synced) { + if(fread(pithdr, 1, 4, infp) != 4) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("macunpack: Premature EOF"); +#endif /* SCAN */ + exit(1); + } + } + synced = 0; + if(strncmp(pithdr, "PEnd", 4) == 0) { + break; + } + if(strncmp(pithdr, "PMa", 3) != 0) { + (void)fprintf(stderr, "File contains non PackIt info %.4s\n", + pithdr); +#ifdef SCAN + do_error("macunpack: File contains non PackIt info"); +#endif /* SCAN */ + exit(1); + } + switch(pithdr[3]) { + case 'g': + case '4': + break; + case '5': + case '6': + if(pithdr[3] == '6') { + (void)fprintf(stderr, "DES-"); + } + (void)fprintf(stderr, "Encrypted file found, trying to sync"); + while(!synced) { + ch = getb(infp); + if(ch == 'P') { + pithdr[0] = ch; + pithdr[1] = ch = getb(infp); + if(ch == 'M') { + pithdr[2] = ch = getb(infp); + if(ch == 'a') { + pithdr[3] = ch = getb(infp); + if((ch >= '4' && ch <= '6') || ch == 'g') { + synced = 1; + } + } + } else if(ch == 'E') { + pithdr[2] = ch = getb(infp); + if(ch == 'n') { + pithdr[3] = ch = getb(infp); + if(ch == 'd') { + synced = 1; + } + } + } + if(!synced) { + (void)ungetc(ch, infp); + } + } + } + (void)fprintf(stderr, ", done.\n"); +#ifdef SCAN + do_idf("", PROTECTED); +#endif /* SCAN */ + continue; + default: + (void)fprintf(stderr, "File contains non PackIt info %.4s\n", + pithdr); +#ifdef SCAN + do_error("macunpack: File contains non PackIt info"); +#endif /* SCAN */ + exit(1); + } + bytes_read = 0; + if(pithdr[3] == '4') { + read_tree(); + decode = huffman; + } else { + decode = nocomp; + } + if(pit_filehdr(&filehdr, decode) == -1) { + (void)fprintf(stderr, "Can't read file header\n"); +#ifdef SCAN + do_error("macunpack: Can't read file header"); +#endif /* SCAN */ + exit(1); + } + bytes_written = filehdr.rlen + filehdr.dlen; + start_info(info, filehdr.rlen, filehdr.dlen); + start_data(); + pit_wrfile(filehdr.dlen, decode); + data_crc = (*updcrc)(INIT_CRC, out_buffer, filehdr.dlen); + start_rsrc(); + pit_wrfile(filehdr.rlen, decode); + data_crc = (*updcrc)(data_crc, out_buffer, filehdr.rlen); + if(decode == nocomp) { + crc = getb(infp); + crc = (crc << 8) | getb(infp); + } else { + crc = (getihuffbyte() & BYTEMASK) | + ((getihuffbyte() & BYTEMASK) << 8); + } + if(crc != data_crc) { + (void)fprintf(stderr, + "CRC error in file: need 0x%04x, got 0x%04x\n", + (int)crc, (int)data_crc); +#ifdef SCAN + do_error("macunpack: CRC error in file"); +#endif /* SCAN */ + exit(1); + } + if(verbose) { + if(decode == nocomp) { + (void)fprintf(stderr, "\tNo compression"); + } else { + (void)fprintf(stderr, "\tHuffman compressed (%4.1f%%)", + 100.0 * bytes_read / bytes_written); + } + } + if(write_it) { + end_file(); + } + if(verbose) { + (void)fprintf(stderr, ".\n"); + } + } +} + +static int pit_filehdr(f, compr) +struct pit_header *f; +int compr; +{ + register int i; + unsigned long crc; + int n; + char hdr[HDRBYTES]; + char ftype[5], fauth[5]; + + for(i = 0; i < INFOBYTES; i++) + info[i] = '\0'; + + if(compr == huffman) { + for(i = 0; i < HDRBYTES; i++) { + hdr[i] = getihuffbyte(); + } + } else { + if(fread(hdr, 1, HDRBYTES, infp) != HDRBYTES) { + return -1; + } + } + crc = INIT_CRC; + crc = (*updcrc)(crc, hdr, HDRBYTES - 2); + + f->hdrCRC = get2(hdr + H_HDRCRC); + if(f->hdrCRC != crc) { + (void)fprintf(stderr, + "\tHeader CRC mismatch: got 0x%04x, need 0x%04x\n", + f->hdrCRC & WORDMASK, (int)crc); + return -1; + } + + n = hdr[H_NLENOFF] & BYTEMASK; + if(n > H_NAMELEN) { + n = H_NAMELEN; + } + info[I_NAMEOFF] = n; + copy(info + I_NAMEOFF + 1, hdr + H_NAMEOFF, n); + transname(hdr + H_NAMEOFF, text, n); + text[n] = '\0'; + + f->rlen = get4(hdr + H_RLENOFF); + f->dlen = get4(hdr + H_DLENOFF); + + write_it = 1; + if(list) { + transname(hdr + H_TYPEOFF, ftype, 4); + transname(hdr + H_AUTHOFF, fauth, 4); + do_indent(indent); + (void)fprintf(stderr, + "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld", + text, ftype, fauth, (long)f->dlen, (long)f->rlen); + if(info_only) { + write_it = 0; + } + if(query) { + write_it = do_query(); + } else { + (void)fputc('\n', stderr); + } + } + + + if(write_it) { + define_name(text); + + copy(info + I_TYPEOFF, hdr + H_TYPEOFF, 4); + copy(info + I_AUTHOFF, hdr + H_AUTHOFF, 4); + copy(info + I_FLAGOFF, hdr + H_FLAGOFF, 2); + copy(info + I_LOCKOFF, hdr + H_LOCKOFF, 2); + copy(info + I_DLENOFF, hdr + H_DLENOFF, 4); + copy(info + I_RLENOFF, hdr + H_RLENOFF, 4); + copy(info + I_CTIMOFF, hdr + H_CTIMOFF, 4); + copy(info + I_MTIMOFF, hdr + H_MTIMOFF, 4); + } + return 1; +} + +static void pit_wrfile(bytes, type) +unsigned long bytes; +int type; +{ + if(bytes == 0) { + return; + } + switch(type) { + case nocomp: + pit_nocomp(bytes); + break; + case huffman: + pit_huffman(bytes); + } +} + +/*---------------------------------------------------------------------------*/ +/* No compression */ +/*---------------------------------------------------------------------------*/ +static void pit_nocomp(ibytes) +unsigned long ibytes; +{ + int n; + + n = fread(out_buffer, 1, (int)ibytes, infp); + if(n != ibytes) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("macunpack: Premature EOF"); +#endif /* SCAN */ + exit(1); + } +} + +/*---------------------------------------------------------------------------*/ +/* Huffman compression */ +/*---------------------------------------------------------------------------*/ +static void pit_huffman(obytes) +unsigned long obytes; +{ + de_huffman(obytes); +} +#else /* PIT */ +int pit; /* keep lint and some compilers happy */ +#endif /* PIT */ + diff --git a/macunpack/pit.h b/macunpack/pit.h new file mode 100755 index 0000000..f47caeb --- /dev/null +++ b/macunpack/pit.h @@ -0,0 +1,32 @@ +#define H_NAMELEN 63 + +#define H_NLENOFF 0 +#define H_NAMEOFF 1 +#define H_TYPEOFF 64 +#define H_AUTHOFF 68 +#define H_FLAGOFF 72 +#define H_LOCKOFF 74 +#define H_DLENOFF 76 +#define H_RLENOFF 80 +#define H_CTIMOFF 84 +#define H_MTIMOFF 88 +#define H_HDRCRC 92 +#define HDRBYTES 94 + +struct pit_header { /* Packit file header (92 bytes) */ + unsigned char nlen; /* number of characters in packed file name */ + char name[63]; /* name of packed file */ + char type[4]; /* file type */ + char auth[4]; /* file creator */ + unsigned short flags; /* file flags (?) */ + unsigned short lock; /* unknown */ + unsigned long dlen; /* number of bytes in data fork */ + unsigned long rlen; /* number of bytes in resource fork */ + unsigned long ctim; /* file creation time */ + unsigned long mtim; /* file modified time */ + unsigned short hdrCRC; /* CRC */ +}; + +#define nocomp 0 +#define huffman 1 + diff --git a/macunpack/pit.o b/macunpack/pit.o new file mode 100644 index 0000000..032b63d Binary files /dev/null and b/macunpack/pit.o differ diff --git a/macunpack/sit.c b/macunpack/sit.c new file mode 100755 index 0000000..88d61cd --- /dev/null +++ b/macunpack/sit.c @@ -0,0 +1,847 @@ +#include "macunpack.h" +#ifdef SIT +#include "globals.h" +#include "sit.h" +#include "crc.h" +#include "../util/util.h" +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "../fileio/kind.h" +#include "../util/masks.h" +#include "huffman.h" + +extern void de_compress(); +extern void core_compress(); +extern void de_huffman(); +extern void de_huffman_end(); +extern void read_tree(); +extern void set_huffman(); +extern void de_lzah(); +extern unsigned char (*lzah_getbyte)(); + +typedef struct methodinfo { + char *name; + int number; +}; + +static struct methodinfo methods[] = { + {"NoComp", nocomp}, + {"RLE", rle}, + {"LZC", lzc}, + {"Huffman", huffman}, + {"LZAH", lzah}, + {"FixHuf", fixhuf}, + {"MW", mw}, +}; +static int sit_nodeptr; + +static int readsithdr(); +static int sit_filehdr(); +static int sit_valid(); +static int sit_checkm(); +static char *sit_methname(); +static void sit_folder(); +static void sit_unstuff(); +static void sit_wrfile(); +static void sit_skip(); +static void sit_nocomp(); +static void sit_rle(); +static void sit_lzc(); +static void sit_huffman(); +static void sit_lzah(); +static unsigned char sit_getbyte(); +static void sit_fixhuf(); +static void sit_dosplit(); +static void sit_mw(); +static void sit_mw_out(); +static int sit_mw_in(); + +static short code6[258] = { + 1024, 512, 256, 256, 256, 256, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 8, 8, 16, 16, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 1, 1, + 1, 1}; +static char sit_buffer[32768]; +static short sit_dict[16385]; +static unsigned long sit_avail; +static int sit_bits_avail; + +void sit() +{ + struct sitHdr sithdr; + struct fileHdr filehdr; + int i; + + set_huffman(HUFF_BE); + core_compress((char *)NULL); + updcrc = arc_updcrc; + crcinit = arc_crcinit; + if(readsithdr(&sithdr) == 0) { + (void)fprintf(stderr, "Can't read file header\n"); +#ifdef SCAN + do_error("macunpack: Can't read file header"); +#endif /* SCAN */ + exit(1); + } + + for(i = 0; i < sithdr.numFiles; i++) { + if(sit_filehdr(&filehdr, 0) == -1) { + (void)fprintf(stderr, "Can't read file header #%d\n", i+1); +#ifdef SCAN + do_error("macunpack: Can't read file header"); +#endif /* SCAN */ + exit(1); + } + if(!sit_valid(filehdr)) { + continue; + } + if(filehdr.compRMethod == sfolder) { + sit_folder(text); + } else { + sit_unstuff(filehdr); + } + } +} + +static int readsithdr(s) +struct sitHdr *s; +{ + char temp[SITHDRSIZE]; + + if(fread(temp, 1, SITHDRSIZE, infp) != SITHDRSIZE) { + return 0; + } + + if(strncmp(temp + S_SIGNATURE, "SIT!", 4) != 0 || + strncmp(temp + S_SIGNATURE2, "rLau", 4) != 0) { + (void)fprintf(stderr, "Not a StuffIt file\n"); + return 0; + } + + s->numFiles = get2(temp + S_NUMFILES); + s->arcLength = get4(temp + S_ARCLENGTH); + + return 1; +} + +static int sit_filehdr(f, skip) +struct fileHdr *f; +int skip; +{ + register int i; + unsigned long crc; + int n; + char hdr[FILEHDRSIZE]; + char ftype[5], fauth[5]; + + for(i = 0; i < INFOBYTES; i++) { + info[i] = '\0'; + } + if(fread(hdr, 1, FILEHDRSIZE, infp) != FILEHDRSIZE) { + (void)fprintf(stderr, "Can't read file header\n"); + return -1; + } + crc = INIT_CRC; + crc = (*updcrc)(crc, hdr, FILEHDRSIZE - 2); + + f->hdrCRC = get2(hdr + F_HDRCRC); + if(f->hdrCRC != crc) { + (void)fprintf(stderr, "Header CRC mismatch: got 0x%04x, need 0x%04x\n", + f->hdrCRC & WORDMASK, (int)crc); + return -1; + } + + n = hdr[F_FNAME] & BYTEMASK; + if(n > F_NAMELEN) { + n = F_NAMELEN; + } + info[I_NAMEOFF] = n; + copy(info + I_NAMEOFF + 1, hdr + F_FNAME + 1, n); + transname(hdr + F_FNAME + 1, text, n); + + f->compRMethod = hdr[F_COMPRMETHOD]; + f->compDMethod = hdr[F_COMPDMETHOD]; + f->rsrcLength = get4(hdr + F_RSRCLENGTH); + f->dataLength = get4(hdr + F_DATALENGTH); + f->compRLength = get4(hdr + F_COMPRLENGTH); + f->compDLength = get4(hdr + F_COMPDLENGTH); + f->rsrcCRC = get2(hdr + F_RSRCCRC); + f->dataCRC = get2(hdr + F_DATACRC); + + write_it = !skip; + if(list && !skip) { + if(f->compRMethod != efolder) { + do_indent(indent); + } + if(f->compRMethod == sfolder) { + (void)fprintf(stderr, "folder=\"%s\"", text); + } else if(f->compRMethod != efolder) { + transname(hdr + F_FTYPE, ftype, 4); + transname(hdr + F_CREATOR, fauth, 4); + (void)fprintf(stderr, + "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld", + text, ftype, fauth, + (long)f->dataLength, (long)f->rsrcLength); + } + if(info_only) { + write_it = 0; + } + if(f->compRMethod != efolder) { + if(query) { + write_it = do_query(); + } else { + (void)fputc('\n', stderr); + } + } + } + + if(write_it) { + define_name(text); + + if(f->compRMethod != sfolder) { + copy(info + I_TYPEOFF, hdr + F_FTYPE, 4); + copy(info + I_AUTHOFF, hdr + F_CREATOR, 4); + copy(info + I_FLAGOFF, hdr + F_FNDRFLAGS, 2); + copy(info + I_DLENOFF, hdr + F_DATALENGTH, 4); + copy(info + I_RLENOFF, hdr + F_RSRCLENGTH, 4); + copy(info + I_CTIMOFF, hdr + F_CREATIONDATE, 4); + copy(info + I_MTIMOFF, hdr + F_MODDATE, 4); + } + } + return 1; +} + +static int sit_valid(f) +struct fileHdr f; +{ + int fr = f.compRMethod, fd = f.compDMethod; + + if(fr == sfolder || fr == efolder) { + return 1; + } + if((fr & prot) || (fd & prot)) { + (void)fprintf(stderr, "\tFile is password protected"); +#ifdef SCAN + do_idf("", PROTECTED); +#endif /* SCAN */ + } else if(fr >= prot || fd >= prot) { + (void)fprintf(stderr, "\tUnknown stuffit flags: %x %x", fr, fd); +#ifdef SCAN + do_idf("", UNKNOWN); +#endif /* SCAN */ + } else if(((1 << fr) & sknown) && ((1 << fd) & sknown)) { + if(sit_checkm(fr) && sit_checkm(fd)) { + return 1; + } + if(!sit_checkm(fr)) { + (void)fprintf(stderr, "\tMethod \"%s\" not implemented", + sit_methname(fr)); + } else { + (void)fprintf(stderr, "\tMethod \"%s\" not implemented", + sit_methname(fd)); + } +#ifdef SCAN + do_idf("", UNKNOWN); +#endif /* SCAN */ + } else { + (void)fprintf(stderr, "\tUnknown compression methods: %x %x", fr, fd); +#ifdef SCAN + do_idf("", UNKNOWN); +#endif /* SCAN */ + } + (void)fprintf(stderr, ", skipping file.\n"); + sit_skip(f.compRLength); + sit_skip(f.compDLength); + return 0; +} + +static int sit_checkm(f) +int f; +{ + switch(f) { + case nocomp: + return 1; + case rle: + return 1; + case lzc: + return 1; + case huffman: + return 1; + case lzah: + return 1; + case fixhuf: + return 1; + case mw: + return 1; + default: + return 0; + } + /* NOTREACHED */ +} + +static char *sit_methname(n) +int n; +{ +int i, nmeths; + nmeths = sizeof(methods) / sizeof(struct methodinfo); + for(i = 0; i < nmeths; i++) { + if(methods[i].number == n) { + return methods[i].name; + } + } + return NULL; +} + +static void sit_folder(name) +char *name; +{ + int i, recurse; + char loc_name[64]; + struct fileHdr filehdr; + + for(i = 0; i < 64; i++) { + loc_name[i] = name[i]; + } + if(write_it || info_only) { + if(write_it) { + do_mkdir(text, info); + } + indent++; + while(1) { + if(sit_filehdr(&filehdr, 0) == -1) { + (void)fprintf(stderr, "Can't read file header #%d\n", i+1); +#ifdef SCAN + do_error("macunpack: Can't read file header"); +#endif /* SCAN */ + exit(1); + } + if(!sit_valid(filehdr)) { + continue; + } + if(filehdr.compRMethod == sfolder) { + sit_folder(text); + } else if(filehdr.compRMethod == efolder) { + break; + } else { + sit_unstuff(filehdr); + } + } + if(write_it) { + enddir(); + } + indent--; + if(list) { + do_indent(indent); + (void)fprintf(stderr, "leaving folder \"%s\"\n", loc_name); + } + } else { + recurse = 0; + while(1) { + if(sit_filehdr(&filehdr, 1) == -1) { + (void)fprintf(stderr, "Can't read file header #%d\n", i+1); +#ifdef SCAN + do_error("macunpack: Can't read file header"); +#endif /* SCAN */ + exit(1); + } + if(filehdr.compRMethod == sfolder) { + recurse++; + } else if(filehdr.compRMethod == efolder) { + recurse--; + if(recurse < 0) { + break; + } + } else { + sit_skip(filehdr.compRLength); + sit_skip(filehdr.compDLength); + } + } + } +} + +static void sit_unstuff(filehdr) +struct fileHdr filehdr; +{ + unsigned long crc; + + if(write_it) { + start_info(info, filehdr.rsrcLength, filehdr.dataLength); + } + if(verbose) { + (void)fprintf(stderr, "\tRsrc: "); + } + if(write_it) { + start_rsrc(); + } + sit_wrfile(filehdr.compRLength, filehdr.rsrcLength, filehdr.compRMethod); + if(write_it) { + crc = (*updcrc)(INIT_CRC, out_buffer, filehdr.rsrcLength); + if(filehdr.rsrcCRC != crc) { + (void)fprintf(stderr, + "CRC error on resource fork: need 0x%04x, got 0x%04x\n", + filehdr.rsrcCRC, (int)crc); +#ifdef SCAN + do_error("macunpack: CRC error on resource fork"); +#endif /* SCAN */ + exit(1); + } + } + if(verbose) { + (void)fprintf(stderr, ", Data: "); + } + if(write_it) { + start_data(); + } + sit_wrfile(filehdr.compDLength, filehdr.dataLength, filehdr.compDMethod); + if(write_it) { + crc = (*updcrc)(INIT_CRC, out_buffer, filehdr.dataLength); + if(filehdr.dataCRC != crc) { + (void)fprintf(stderr, + "CRC error on data fork: need 0x%04x, got 0x%04x\n", + filehdr.dataCRC, (int)crc); +#ifdef SCAN + do_error("macunpack: CRC error on data fork"); +#endif /* SCAN */ + exit(1); + } + end_file(); + } + if(verbose) { + (void)fprintf(stderr, ".\n"); + } +} + +static void sit_wrfile(ibytes, obytes, type) +unsigned long ibytes, obytes; +unsigned char type; +{ + if(ibytes == 0) { + if(verbose) { + (void)fprintf(stderr, "empty"); + } + return; + } + switch(type) { + case nocomp: /* no compression */ + if(verbose) { + (void)fprintf(stderr, "No compression"); + } + if(write_it) { + sit_nocomp(ibytes); + } else { + sit_skip(ibytes); + } + break; + case rle: /* run length encoding */ + if(verbose) { + (void)fprintf(stderr, + "RLE compressed (%4.1f%%)", 100.0 * ibytes / obytes); + } + if(write_it) { + sit_rle(ibytes); + } else { + sit_skip(ibytes); + } + break; + case lzc: /* LZC compression */ + if(verbose) { + (void)fprintf(stderr, + "LZC compressed (%4.1f%%)", 100.0 * ibytes / obytes); + } + if(write_it) { + sit_lzc(ibytes); + } else { + sit_skip(ibytes); + } + break; + case huffman: /* Huffman compression */ + if(verbose) { + (void)fprintf(stderr, + "Huffman compressed (%4.1f%%)", 100.0 * ibytes / obytes); + } + if(write_it) { + sit_huffman(obytes); + } else { + sit_skip(ibytes); + } + break; + case lzah: /* LZAH compression */ + if(verbose) { + (void)fprintf(stderr, + "LZAH compressed (%4.1f%%)", 100.0 * ibytes / obytes); + } + if(write_it) { + sit_lzah(obytes); + } else { + sit_skip(ibytes); + } + break; + case fixhuf: /* FixHuf compression */ + if(verbose) { + (void)fprintf(stderr, + "FixHuf compressed (%4.1f%%)", 100.0 * ibytes / obytes); + } + if(write_it) { + sit_fixhuf(ibytes); + } else { + sit_skip(ibytes); + } + break; + case mw: /* MW compression */ + if(verbose) { + (void)fprintf(stderr, + "MW compressed (%4.1f%%)", 100.0 * ibytes / obytes); + } + if(write_it) { + sit_mw(ibytes); + } else { + sit_skip(ibytes); + } + break; + default: + (void)fprintf(stderr, "Unknown compression method %2x\n", type); +#ifdef SCAN + do_idf("", UNKNOWN); +#endif /* SCAN */ + exit(1); + } +} + +/* skip stuffit file */ +static void sit_skip(ibytes) +unsigned long ibytes; +{ + while(ibytes != 0) { + if(getc(infp) == EOF) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("macunpack: Premature EOF"); +#endif /* SCAN */ + exit(1); + } + ibytes--; + } +} + +/*---------------------------------------------------------------------------*/ +/* Method 0: No compression */ +/*---------------------------------------------------------------------------*/ +static void sit_nocomp(ibytes) +unsigned long ibytes; +{ + int n; + + n = fread(out_buffer, 1, (int)ibytes, infp); + if(n != ibytes) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("macunpack: Premature EOF"); +#endif /* SCAN */ + exit(1); + } +} + +/*---------------------------------------------------------------------------*/ +/* Method 1: Run length encoding */ +/*---------------------------------------------------------------------------*/ +static void sit_rle(ibytes) +unsigned long ibytes; +{ + int ch, lastch, n, i; + + while(ibytes != 0) { + ch = getb(infp) & BYTEMASK; + ibytes--; + if(ch == ESC) { + n = (getb(infp) & BYTEMASK) - 1; + ibytes--; + if(n < 0) { + *out_ptr++ = ESC; + lastch = ESC; + n = 1; + } else { + for(i = 0; i < n; i++) { + *out_ptr++ = lastch; + } + } + } else { + *out_ptr++ = ch; + lastch = ch; + } + } +} + +/*---------------------------------------------------------------------------*/ +/* Method 2: LZC compressed */ +/*---------------------------------------------------------------------------*/ +static void sit_lzc(ibytes) +unsigned long ibytes; +{ + de_compress(ibytes, 14); +} + +/*---------------------------------------------------------------------------*/ +/* Method 3: Huffman compressed */ +/*---------------------------------------------------------------------------*/ +static void sit_huffman(obytes) +unsigned long obytes; +{ + read_tree(); + de_huffman(obytes); +} + +/*---------------------------------------------------------------------------*/ +/* Method 5: LZ compression plus adaptive Huffman encoding */ +/*---------------------------------------------------------------------------*/ +static void sit_lzah(obytes) +unsigned long obytes; +{ + lzah_getbyte = sit_getbyte; + de_lzah(obytes); +} + +static unsigned char sit_getbyte() +{ + return getb(infp); +} + +/*---------------------------------------------------------------------------*/ +/* Method 6: Compression with a fixed Huffman encoding */ +/*---------------------------------------------------------------------------*/ +static void sit_fixhuf(ibytes) +unsigned long ibytes; +{ + int i, sum, codes, sym, num; + char byte_int[4], byte_short[2]; + long size; + int sign; + char *tmp_ptr, *ptr, *end_ptr; + + sum = 0; + for(i = 0; i < 258; i++) { + sum += code6[i]; + nodelist[i + 1].flag = 1; + } + sit_nodeptr = 258; + sit_dosplit(0, sum, 1, 258); + while(ibytes > 0) { + if(fread(byte_int, 1, 4, infp) != 4) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("Premature EOF"); +#endif /* SCAN */ + exit(1); + } + ibytes -= 4; + size = (long)get4(byte_int); + sign = 0; + if(size < 0) { + size = - size; + sign = 1; + } + size -= 4; + if(sign) { + ibytes -= size; + if(fread(sit_buffer, 1, (int)size, infp) != size) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("Premature EOF"); +#endif /* SCAN */ + exit(1); + } + } else { + ibytes -= size; + if(fread(byte_int, 1, 4, infp) != 4) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("Premature EOF"); +#endif /* SCAN */ + exit(1); + } + size -= 4; + if(fread(byte_short, 1, 2, infp) != 2) { + (void)fprintf(stderr, "Premature EOF\n"); +#ifdef SCAN + do_error("Premature EOF"); +#endif /* SCAN */ + exit(1); + } + size -= 2; + codes = get2(byte_short); + for(i = 1; i <= codes; i++) { + nodelist[i].byte = getb(infp); + } + size -= codes; + clrhuff(); + nodelist[257].byte = 0x100; + nodelist[258].byte = 0x100; + tmp_ptr = out_ptr; + out_ptr = &(sit_buffer[0]); + bytesread = 0; + de_huffman_end(0x100); + while(bytesread < size) { + (void)getb(infp); + bytesread++; + } + size = get4(byte_int); + out_ptr = tmp_ptr; + } + ptr = sit_buffer; + end_ptr = ptr + size; + while(ptr < end_ptr) { + num = *ptr++ & BYTEMASK; + if(num < 0x80) { + while(num-- >= 0) { + *out_ptr++ = *ptr++; + } + } else if(num != 0x80) { + sym = *ptr++; + while(num++ <= 0x100) { + *out_ptr++ = sym; + } + } + } + } +} + +static void sit_dosplit(ptr, sum, low, upp) +int ptr, sum, low, upp; +{ + int i, locsum; + + sum = sum / 2; + locsum = 0; + i = low; + while(locsum < sum) { + locsum += code6[i++ - 1]; + } + if(low == i - 1) { + nodelist[ptr].zero = nodelist + low; + } else { + nodelist[ptr].zero = nodelist + ++sit_nodeptr; + sit_dosplit(sit_nodeptr, sum, low, i - 1); + } + if(upp == i) { + nodelist[ptr].one = nodelist + upp; + } else { + nodelist[ptr].one = nodelist + ++sit_nodeptr; + sit_dosplit(sit_nodeptr, sum, i, upp); + } +} + +/*---------------------------------------------------------------------------*/ +/* Method 8: Compression with a MW encoding */ +/*---------------------------------------------------------------------------*/ +static void sit_mw(ibytes) +unsigned long ibytes; +{ + int ptr; + int max, max1, bits; + char *out_buf; + + out_buf = out_buffer; + sit_bits_avail = 0; + sit_avail = 0; +start_over: + max = 256; + max1 = max + max; + bits = 9; + ptr = sit_mw_in(bits, &ibytes); + if(ptr == max) { + goto start_over; + } + if(ptr > max || ptr < 0) { + out_buffer = out_buf; + return; + } + sit_dict[255] = ptr; + sit_mw_out(ptr); + while(1) { + ptr = sit_mw_in(bits, &ibytes); + if(ptr == max) { + goto start_over; + } + if(ptr > max || ptr < 0) { + out_buffer = out_buf; + return; + } + sit_dict[max++] = ptr; + if(max == max1) { + max1 <<= 1; + bits++; + } + sit_mw_out(ptr); + } +} + +static void sit_mw_out(ptr) +int ptr; +{ + int stack_ptr; + int stack[16384]; + + stack_ptr = 1; + stack[0] = ptr; + while(stack_ptr) { + ptr = stack[--stack_ptr]; + while(ptr >= 256) { + stack[stack_ptr++] = sit_dict[ptr]; + ptr = sit_dict[ptr - 1]; + } + *out_buffer++ = ptr; + } +} + +static int sit_mw_in(bits, ibytes) +int bits; +unsigned long *ibytes; +{ + int res, res1; + + while(bits > sit_bits_avail) { + if(*ibytes == 0) { + return -1; + } + (*ibytes)--; + sit_avail += (getb(infp) & BYTEMASK) << sit_bits_avail; + sit_bits_avail += 8; + } + res1 = sit_avail >> bits; + res = sit_avail ^ (res1 << bits); + sit_avail = res1; + sit_bits_avail -= bits; + return res; +} + +#else /* SIT */ +int sit; /* keep lint and some compilers happy */ +#endif /* SIT */ diff --git a/macunpack/sit.h b/macunpack/sit.h new file mode 100755 index 0000000..383417b --- /dev/null +++ b/macunpack/sit.h @@ -0,0 +1,95 @@ +#define S_SIGNATURE 0 +#define S_NUMFILES 4 +#define S_ARCLENGTH 6 +#define S_SIGNATURE2 10 +#define S_VERSION 14 +#define SITHDRSIZE 22 + +#define F_COMPRMETHOD 0 +#define F_COMPDMETHOD 1 +#define F_FNAME 2 +#define F_FTYPE 66 +#define F_CREATOR 70 +#define F_FNDRFLAGS 74 +#define F_CREATIONDATE 76 +#define F_MODDATE 80 +#define F_RSRCLENGTH 84 +#define F_DATALENGTH 88 +#define F_COMPRLENGTH 92 +#define F_COMPDLENGTH 96 +#define F_RSRCCRC 100 +#define F_DATACRC 102 +#define F_HDRCRC 110 +#define FILEHDRSIZE 112 + +typedef long OSType; + +typedef struct sitHdr { /* 22 bytes */ + OSType signature; /* = 'SIT!' -- for verification */ + unsigned short numFiles; /* number of files in archive */ + unsigned long arcLength; /* length of entire archive incl. + hdr. -- for verification */ + OSType signature2; /* = 'rLau' -- for verification */ + unsigned char version; /* version number */ + char reserved[7]; +}; + +typedef struct fileHdr { /* 112 bytes */ + unsigned char compRMethod; /* rsrc fork compression method */ + unsigned char compDMethod; /* data fork compression method */ + unsigned char fName[64]; /* a STR63 */ + OSType fType; /* file type */ + OSType fCreator; /* er... */ + unsigned short FndrFlags; /* copy of Finder flags. For our + purposes, we can clear: + busy,onDesk */ + unsigned long creationDate; + unsigned long modDate; /* !restored-compat w/backup prgms */ + unsigned long rsrcLength; /* decompressed lengths */ + unsigned long dataLength; + unsigned long compRLength; /* compressed lengths */ + unsigned long compDLength; + unsigned short rsrcCRC; /* crc of rsrc fork */ + unsigned short dataCRC; /* crc of data fork */ + char reserved[6]; + unsigned short hdrCRC; /* crc of file header */ +}; + + +/* file format is: + sitArchiveHdr + file1Hdr + file1RsrcFork + file1DataFork + file2Hdr + file2RsrcFork + file2DataFork + . + . + . + fileNHdr + fileNRsrcFork + fileNDataFork +*/ + + + +/* compression methods */ +#define nocomp 0 /* just read each byte and write it to archive */ +#define rle 1 /* RLE compression */ +#define lzc 2 /* LZC compression */ +#define huffman 3 /* Huffman compression */ +#define lzah 5 /* LZ with adaptive Huffman */ +#define fixhuf 6 /* Fixed Huffman table */ +#define mw 8 /* Miller-Wegman encoding */ +/* this bit says whether the file is protected or not */ +#define prot 16 /* password protected bit */ +/* rsrc & data compress are identical here: */ +#define sfolder 32 /* start of folder */ +#define efolder 33 /* end of folder */ +#define sknown 0x16f /* known compression methods */ + +/* all other numbers are reserved */ + +#define ESC 0x90 /* repeat packing escape */ + diff --git a/macunpack/sit.o b/macunpack/sit.o new file mode 100644 index 0000000..eba74cb Binary files /dev/null and b/macunpack/sit.o differ diff --git a/macunpack/stf.c b/macunpack/stf.c new file mode 100755 index 0000000..3c33fa1 --- /dev/null +++ b/macunpack/stf.c @@ -0,0 +1,223 @@ +#include "macunpack.h" +#ifdef STF +#include "stf.h" +#include "globals.h" +#include "huffman.h" +#include "../util/curtime.h" +#include "../fileio/wrfile.h" +#include "../fileio/machdr.h" +#include "../util/util.h" + +extern void de_huffman(); +extern void set_huffman(); + +typedef struct{ + int num; + int next; +} table_struct; + +static table_struct table[511]; +static char length[256]; + +static void stf_wrfile(); +static void stf_wrfork(); +static void stf_construct(); + +void stf(ibytes) +unsigned long ibytes; +{ + char magic[3], fauth[5], ftype[5]; + int filel, i; + unsigned int rsrcLength, dataLength; + unsigned long curtime; + + set_huffman(HUFF_LE); + for(i = 0; i < 3; i++) { + magic[i] = getb(infp); + } + if(strncmp(magic, MAGIC, 3)) { + (void)fprintf(stderr, "Error in magic header.\n"); +#ifdef SCAN + do_error("macunpack: Error in magic header"); +#endif /* SCAN */ + exit(1); + } + for(i = 0; i < INFOBYTES; i++) { + info[i] = 0; + } + filel = getb(infp); + info[I_NAMEOFF] = filel; + i = filel; + for(i = 1; i <= filel; i++) { + info[I_NAMEOFF + i] = getb(infp); + } + for(i = 0; i < 4; i++) { + info[I_TYPEOFF + i] = getb(infp); + } + for(i = 0; i < 4; i++) { + info[I_AUTHOFF + i] = getb(infp); + } + curtime = (unsigned long)time((time_t *)0) + TIMEDIFF; + put4(info + I_CTIMOFF, curtime); + put4(info + I_MTIMOFF, curtime); + rsrcLength = 0; + for(i = 0; i < 4; i++) { + rsrcLength = (rsrcLength << 8) + getb(infp); + } + put4(info + I_RLENOFF, (unsigned long)rsrcLength); + dataLength = 0; + for(i = 0; i < 4; i++) { + dataLength = (dataLength << 8) + getb(infp); + } + put4(info + I_DLENOFF, (unsigned long)dataLength); + ibytes -= filel + 20; + write_it = 1; + if(list) { + transname(info + I_NAMEOFF + 1, text, (int)info[I_NAMEOFF]); + transname(info + I_TYPEOFF, ftype, 4); + transname(info + I_AUTHOFF, fauth, 4); + do_indent(indent); + (void)fprintf(stderr, + "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld", + text, ftype, fauth, (long)dataLength, (long)rsrcLength); + if(info_only) { + write_it = 0; + } + if(query) { + write_it = do_query(); + } else { + (void)fputc('\n', stderr); + } + } + stf_wrfile((unsigned long)rsrcLength, (unsigned long)dataLength, ibytes); +} + +static void stf_wrfile(rsrcLength, dataLength, ibytes) +unsigned long rsrcLength, dataLength, ibytes; +{ + unsigned long num = 0; + + if(write_it) { + define_name(text); + start_info(info, rsrcLength, dataLength); + start_rsrc(); + stf_wrfork(&num, rsrcLength, 0); + start_data(); + stf_wrfork(&num, rsrcLength + dataLength, (int)(rsrcLength & 0xfff)); + end_file(); + } else { + for(num = 0; num < ibytes; num++) { + (void)getb(infp); + } + } + if(verbose) { + (void)fprintf(stderr, "\tHuffman compressed (%4.1f%%).\n", + 100.0 * ibytes / (rsrcLength + dataLength)); + } +} + +static void stf_wrfork(num, towrite, offs) +unsigned long *num, towrite; +int offs; +{ + int c, k, max, i, i1; + char *tmp_out_ptr; + + while(*num < towrite) { + if((*num & 0xfff) == 0) { + clrhuff(); + c = getb(infp) & 0xff; + k = c; + max = 0; + for(i = 0; i < k; i++) { + c = getb(infp) & 0xff; + nodelist[i + 1].flag = 1; + nodelist[i + 1].byte = i + 1; + table[i + 1].num = c; + table[i + 1].next = 0; + if(c > max) { + max = c; + } + } + for(i = k; i < 32; i++) { + nodelist[i + 1].flag = 1; + nodelist[i + 1].byte = i + 1; + table[i + 1].num = 0; + table[i + 1].next = 0; + } + k = 0; + for(i = 0; i <= max; i++) { + for(i1 = 1; i1 < 33; i1++) { + if(table[i1].num == i) { + table[k].next = i1; + k = i1; + } + } + } + stf_construct(32); + tmp_out_ptr = out_ptr; + out_ptr = length; + de_huffman((unsigned long)256); + out_ptr = tmp_out_ptr; + for(i = 1; i < 257; i++) { + table[i].num = 0x40000000 >> length[i - 1]; + nodelist[i].flag = 1; + nodelist[i].byte = i - 1; + table[i].next = 0; + } + k = 0; + for(i = 1; i < 0x40000000; i <<= 1) { + for(i1 = 1; i1 < 257; i1++) { + if(table[i1].num == i) { + table[k].next = i1; + k = i1; + } + } + } + stf_construct(256); + } + i = 0x1000 - offs; + offs = 0; + if(i > towrite - *num) { + i = towrite - *num; + } + de_huffman((unsigned long)i); + *num += i; + } +} + +static void stf_construct(n) +int n; +{ + int i, i1, i2, j1, k; + + j1 = n + 1; + i = table[0].next; + i1 = table[i].next; + while(table[i1].next != 0) { + k = table[i].num + table[i1].num; + table[j1].num = k; + nodelist[j1].flag = 0; + nodelist[j1].zero = nodelist + i; + nodelist[j1].one = nodelist + i1; + i2 = i1; + i = table[i2].next; + while(i != 0 && table[i].num <= k) { + i2 = i; + i = table[i].next; + } + table[j1].next = i; + table[i2].next = j1; + i = table[i1].next; + i1 = table[i].next; + j1++; + } + table[0].num = table[i].num + table[i1].num; + nodelist[0].flag = 0; + nodelist[0].zero = nodelist + i; + nodelist[0].one = nodelist + i1; +} +#else /* STF */ +int stf; /* keep lint and some compilers happy */ +#endif /* STF */ + diff --git a/macunpack/stf.h b/macunpack/stf.h new file mode 100755 index 0000000..5d5a9bd --- /dev/null +++ b/macunpack/stf.h @@ -0,0 +1,15 @@ +#define MAGIC "RTH" + +#define S_MAGIC 0 +#define S_FLENGTH 3 +#define S_RSRCLNGTH 3 /* + NAMELENGTH */ +#define S_DATALNGTH 7 /* + NAMELENGTH */ + +typedef struct fileHdr { + char magic[3]; + char flength; + char fname[32]; /* actually flength */ + unsigned long rsrcLength; + unsigned long dataLength; +}; + diff --git a/macunpack/stf.o b/macunpack/stf.o new file mode 100644 index 0000000..2f3ffc0 Binary files /dev/null and b/macunpack/stf.o differ diff --git a/macunpack/zma.c b/macunpack/zma.c new file mode 100755 index 0000000..371d7eb --- /dev/null +++ b/macunpack/zma.c @@ -0,0 +1,389 @@ +#include "macunpack.h" +#ifdef ZMA +#include "globals.h" +#include "zma.h" +#include "crc.h" +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "../fileio/kind.h" +#include "../util/masks.h" +#include "../util/util.h" + +extern char *malloc(); +extern char *realloc(); +extern void de_lzh(); + +/* We do allow for possible backpointing, so we allocate the archive in core */ +static char *zma_archive; +static char *zma_current; +static char *zma_filestart; +static unsigned long zma_length; +static long zma_archlength; + +static int zma_filehdr(); +static void zma_folder(); +static void zma_mooz(); +static void zma_wrfile(); +static void zma_nocomp(); +static void zma_lzh(); + +void zma(start, length) + char *start; + unsigned long length; +{ + struct fileHdr filehdr; + int i, toread; + + if(length != 0) { + if(zma_archlength < length) { + if(zma_archlength == 0) { + zma_archive = malloc((unsigned)length); + } else { + zma_archive = realloc(zma_archive, (unsigned)length); + } + zma_archlength = length; + if(zma_archive == NULL) { + (void)fprintf(stderr, "Insufficient memory, aborting\n"); + exit(1); + } + } + if(fread(zma_archive, 1, (int)length, infp) != length) { + (void)fprintf(stderr, "Can't read archive.\n"); +#ifdef SCAN + do_error("macunpack: Can't read archive"); +#endif /* SCAN */ + exit(1); + } + zma_length = get4(zma_archive + ZMAHDRS + 1); + if(zma_length != length) { + (void)fprintf(stderr, "Archive length mismatch.\n"); +#ifdef SCAN + do_error("macunpack: Archive length mismatch"); +#endif /* SCAN */ + exit(1); + } + } else { + zma_length = get4(start + ZMAHDRS + 1); + if(zma_archlength < zma_length) { + if(zma_archlength == 0) { + zma_archive = malloc((unsigned)zma_length); + } else { + zma_archive = realloc(zma_archive, (unsigned)zma_length); + } + zma_archlength = zma_length; + if(zma_archive == NULL) { + (void)fprintf(stderr, "Insufficient memory, aborting\n"); + exit(1); + } + } + if(zma_archive == NULL) { + (void)fprintf(stderr, "Insufficient memory, aborting\n"); + exit(1); + } + for(i = 0; i <= ZMAHDRS2; i++) { + zma_archive[i] = start[i]; + } + toread = zma_length - ZMAHDRS2 - 1; + if(fread(zma_archive + ZMAHDRS2 + 1, 1, toread, infp) != toread) { + (void)fprintf(stderr, "Can't read archive.\n"); +#ifdef SCAN + do_error("macunpack: Can't read archive"); +#endif /* SCAN */ + exit(1); + } + } + /* Consistency checks */ + if(zma_archive[0] != 0) { + (void)fprintf(stderr, "Not a \"Zoom\" archive after all, aborting\n"); + exit(1); + } + if(strncmp(zma_archive + 1, ZMAHDR, ZMAHDRS)) { + (void)fprintf(stderr, "Not a \"Zoom\" archive after all, aborting\n"); + exit(1); + } + zma_current = zma_archive + 8; + updcrc = arc_updcrc; + crcinit = arc_crcinit; + while(zma_current != zma_archive) { + if(zma_filehdr(&filehdr, 0) == -1) { + (void)fprintf(stderr, "Can't find file header./n"); +#ifdef SCAN + do_error("macunpack: Can't find file header"); +#endif /* SCAN */ + exit(1); + } + zma_filestart = zma_current + filehdr.hlen; + if(filehdr.what == z_dir) { + zma_folder(filehdr); + } else { + zma_mooz(filehdr); + } + zma_current = zma_archive + filehdr.next; + } +} + +static int zma_filehdr(f, skip) +struct fileHdr *f; +int skip; +{ + register int i; + int n; + char ftype[5], fauth[5]; + + if(zma_current - zma_archive + Z_HDRSIZE > zma_length) { + return -1; + } + for(i = 0; i < INFOBYTES; i++) { + info[i] = '\0'; + } + + n = zma_current[Z_FNAME] & BYTEMASK; + if(n > F_NAMELEN) { + n = F_NAMELEN; + } + info[I_NAMEOFF] = n; + copy(info + I_NAMEOFF + 1, zma_current + Z_FNAME + 1, n); + transname(zma_current + Z_FNAME + 1, text, n); + + f->what = zma_current[Z_WHAT]; + f->rsrcLength = get4(zma_current + Z_URLEN); + f->dataLength = get4(zma_current + Z_UDLEN); + f->compRLength = get4(zma_current + Z_CRLEN); + f->compDLength = get4(zma_current + Z_CDLEN); + f->rsrcCRC = get2(zma_current + Z_RCRC); + f->dataCRC = get2(zma_current + Z_DCRC); + f->hlen = zma_current[Z_HLEN]; + f->next = get4(zma_current + Z_NEXT); + if(f->what == z_dir) { /* A hack */ + f->conts = get4(zma_current + Z_AUTH); + } + /* Set rsrc fork sizes correctly */ + f->rsrcLength -= f->dataLength; + f->compRLength -= f->compDLength; + + write_it = !skip; + if(f->what & 0x80) { + write_it = 0; + f->what = -f->what; + f->deleted = 1; + return 0; + } + f->deleted = 0; + if(list && !skip) { + do_indent(indent); + if(f->what == z_dir) { + (void)fprintf(stderr, "folder=\"%s\"", text); + } else { + transname(zma_current + Z_TYPE, ftype, 4); + transname(zma_current + Z_AUTH, fauth, 4); + (void)fprintf(stderr, + "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld", + text, ftype, fauth, + (long)f->dataLength, (long)f->rsrcLength); + } + switch(f->what) { + case z_plug: + (void)fputc('\n', stderr); + (void)fprintf(stderr, + "\tFile uses custom processing, cannot handle.\n"); + write_it = 0; + return 0; + case z_dir: + case z_file: + case z_plain: + break; + default: + (void)fputc('\n', stderr); + (void)fprintf(stderr, + "\tEh, do not understand this (%d); skipped.\n", f->what); + write_it = 0; + return 0; + } + + if(info_only) { + write_it = 0; + } + if(query) { + write_it = do_query(); + } else { + (void)fputc('\n', stderr); + } + } + + + if(write_it) { + define_name(text); + + if(f->what != z_dir) { + copy(info + I_TYPEOFF, zma_current + Z_TYPE, 4); + copy(info + I_AUTHOFF, zma_current + Z_AUTH, 4); + copy(info + I_FLAGOFF, zma_current + Z_FLAGS, 2); + copy(info + I_DLENOFF, zma_current + Z_UDLEN, 4); + put4(zma_current + Z_URLEN, f->rsrcLength); + copy(info + I_RLENOFF, zma_current + Z_URLEN, 4); + copy(info + I_CTIMOFF, zma_current + Z_MDATE, 4); + copy(info + I_MTIMOFF, zma_current + Z_MDATE, 4); + } + } + return 1; +} + +static void zma_folder(fhdr) +struct fileHdr fhdr; +{ + int i; + char loc_name[64]; + struct fileHdr filehdr; + + for(i = 0; i < 64; i++) { + loc_name[i] = text[i]; + } + zma_current = zma_archive + fhdr.conts; + if(write_it || info_only) { + if(write_it) { + do_mkdir(text, info); + } + indent++; + while(zma_current != zma_archive) { + if(zma_filehdr(&filehdr, 0) == -1) { + (void)fprintf(stderr, "Can't find file header.\n"); +#ifdef SCAN + do_error("macunpack: Can't find file header"); +#endif /* SCAN */ + exit(1); + } + zma_filestart = zma_current + filehdr.hlen; + if(filehdr.what == z_dir) { + zma_folder(filehdr); + } else { + zma_mooz(filehdr); + } + zma_current = zma_archive + filehdr.next; + } + if(write_it) { + enddir(); + } + indent--; + if(list) { + do_indent(indent); + (void)fprintf(stderr, "leaving folder \"%s\"\n", loc_name); + } + } +} + +static void zma_mooz(filehdr) +struct fileHdr filehdr; +{ + unsigned long crc; + + if(write_it) { + start_info(info, filehdr.rsrcLength, filehdr.dataLength); + } + if(verbose) { + (void)fprintf(stderr, "\tData: "); + } + if(write_it) { + start_data(); + } + zma_wrfile(filehdr.compDLength, filehdr.dataLength, filehdr.what); + if(write_it) { + crc = (*updcrc)(INIT_CRC, out_buffer, filehdr.dataLength); + if(filehdr.dataCRC != crc) { + (void)fprintf(stderr, + "CRC error on data fork: need 0x%04x, got 0x%04x\n", + (int)filehdr.dataCRC, (int)crc); +#ifdef SCAN + do_error("macunpack: CRC error on data fork"); +#endif /* SCAN */ + exit(1); + } + } + if(verbose) { + (void)fprintf(stderr, ", Rsrc: "); + } + if(write_it) { + start_rsrc(); + } + zma_wrfile(filehdr.compRLength, filehdr.rsrcLength, filehdr.what); + if(write_it) { + crc = (*updcrc)(INIT_CRC, out_buffer, filehdr.rsrcLength); + if(filehdr.rsrcCRC != crc) { + (void)fprintf(stderr, + "CRC error on resource fork: need 0x%04x, got 0x%04x\n", + (int)filehdr.rsrcCRC, (int)crc); +#ifdef SCAN + do_error("macunpack: CRC error on resource fork"); +#endif /* SCAN */ + exit(1); + } + end_file(); + } + if(verbose) { + (void)fprintf(stderr, ".\n"); + } +} + +static void zma_wrfile(ibytes, obytes, type) +unsigned long ibytes, obytes; +char type; +{ + if(ibytes == 0) { + if(verbose) { + (void)fprintf(stderr, "empty"); + } + return; + } + switch(type) { + case z_plain: /* no compression */ + if(verbose) { + (void)fprintf(stderr, "No compression"); + } + if(write_it) { + zma_nocomp(ibytes); + } + break; + case z_file: /* lzh compression */ + if(verbose) { + (void)fprintf(stderr, + "LZH compressed (%4.1f%%)", 100.0 * ibytes / obytes); + } + if(write_it) { + zma_lzh(ibytes); + } + break; + default: + (void)fprintf(stderr, "Unknown compression method %2x\n", type); +#ifdef SCAN + do_idf("", UNKNOWN); +#endif /* SCAN */ + exit(1); + } +} + +/*---------------------------------------------------------------------------*/ +/* No compression */ +/*---------------------------------------------------------------------------*/ +static void zma_nocomp(ibytes) +unsigned long ibytes; +{ + int n = ibytes; + char *ptr = out_buffer; + + while(n-- > 0) { + *ptr++ = *zma_filestart++; + } +} + +/*---------------------------------------------------------------------------*/ +/* LZ compression plus Huffman encoding */ +/*---------------------------------------------------------------------------*/ +static void zma_lzh(ibytes) +unsigned long ibytes; +{ + /* Controlled by ibutes only */ + de_lzh((long)ibytes, (long)(-1), &zma_filestart, 13); +} +#else /* ZMA */ +int zma; /* keep lint and some compilers happy */ +#endif /* ZMA */ + diff --git a/macunpack/zma.h b/macunpack/zma.h new file mode 100755 index 0000000..04bfc9f --- /dev/null +++ b/macunpack/zma.h @@ -0,0 +1,53 @@ +#include "zmahdr.h" + +#define Z_HDRSIZE 78 + +#define Z_WHAT 0 /* What kind of data? */ +#define Z_HLEN 1 /* Header length */ +#define Z_BFLAGS 2 /* Boolean flags */ +#define Z_NEXT 4 /* Pointer to next entry */ +#define Z_CRLEN 8 /* Length compressed resource */ +#define Z_CDLEN 12 /* Length compressed data */ +#define Z_URLEN 16 /* Length uncompressed resource */ +#define Z_UDLEN 20 /* Length uncompressed data */ +#define Z_TYPE 24 /* File type */ +#define Z_AUTH 28 /* File creator */ +#define Z_CONTS 28 /* Directory contents pointer; overlayed */ +#define Z_MDATE 32 /* Date */ +#define Z_COMMENT 36 /* Comment offset, currently unused */ +#define Z_FLAGS 40 /* Finder flags */ +#define Z_DCRC 42 /* Data crc */ +#define Z_RCRC 44 /* Resource crc */ +#define Z_FNAME 46 /* File name length and name */ + +typedef struct fileHdr { /* 78 bytes */ + char deleted; /* Not in original, split off from: */ + char what; /* What kind? Negative if deleted */ + unsigned char hlen ; /* Header length */ + unsigned short boolFlags; /* Boolean flags */ + unsigned long next; /* Next entry */ + unsigned long compRLength; /* The compressed lengths. */ + unsigned long compDLength; /* For dirs, the second is # entries */ + unsigned long rsrcLength; /* The uncompressed lengths. */ + unsigned long dataLength; + unsigned long fType; /* file type */ + unsigned long fCreator; /* er... */ + unsigned long modDate; /* !restored-compat w/backup prgms */ + unsigned long comment; /* Comment offset */ + unsigned short FndrFlags; /* copy of Finder flags. For our + purposes, we can clear: + busy,onDesk */ + unsigned short dataCRC; /* Data fork crc */ + unsigned short rsrcCRC; /* Resource fork crc */ + unsigned char fName[32]; /* a STR32 */ + /* The following are overlayed in the original structure */ + unsigned long conts; /* Pointer to directory contents */ +}; + +/* zma types (see what) */ +#define z_noth 0 /* ??? */ +#define z_file 1 /* file is compressed */ +#define z_plain 2 /* file is uncompressed */ +#define z_dir 3 /* directory */ +#define z_plug 4 /* for plug in, not supported */ + diff --git a/macunpack/zma.o b/macunpack/zma.o new file mode 100644 index 0000000..86d424d Binary files /dev/null and b/macunpack/zma.o differ diff --git a/macunpack/zmahdr.h b/macunpack/zmahdr.h new file mode 100755 index 0000000..c1acfc7 --- /dev/null +++ b/macunpack/zmahdr.h @@ -0,0 +1,4 @@ +#define ZMAHDR "\005\237\032" +#define ZMAHDRS 3 +#define ZMAHDRS2 7 + diff --git a/makefile b/makefile new file mode 100755 index 0000000..6a94a0e --- /dev/null +++ b/makefile @@ -0,0 +1,78 @@ +SHELL = /bin/sh +BINDIR = /ufs/dik/tmpbin +# Use the following flags on the CF macro definition as needed. +# +# -DBSD if you are on a BSD system +# +# -DTYPES_H if your system has /usr/include/sys/types.h +# +# -DDIRENT_H if your system has /usr/include/dirent.h +# +# -DTERMIOS_H if your system has /usr/include/sys/termios.h +# +# -DNODOT if you do not want to create files with an initial period +# +# -DLATIN1 if your system supports LATIN-1 and you want to use it +# +# Note you can use at most one of the following four! +# +# -DNOMKDIR if your system does not have the mkdir system call +# +# -DAUFS if you want to use an AUFS file system +# +# -DAUFSPLUS if you use CAP 6.0 and want to use times on files +# +# -DAPPLEDOUBLE if you want to be able to use an AppleDouble file system +# +CF = -DBSD -DTYPES_H -DDIRENT_H -DTERMIOS_H -DNODOT -DAPPLEDOUBLE + +all: + (cd crc; make CF='$(CF)') + (cd util; make CF='$(CF)') + (cd fileio; make CF='$(CF)') + (cd macunpack; make CF='$(CF)') + (cd hexbin; make CF='$(CF)') + (cd mixed; make CF='$(CF)') + (cd binhex; make CF='$(CF)') + (cd comm; make CF='$(CF)') + +clean: + (cd crc; make clean) + (cd util; make clean) + (cd fileio; make clean) + (cd macunpack; make clean) + (cd hexbin; make clean) + (cd mixed; make clean) + (cd binhex; make clean) + (cd comm; make clean) + +clobber: + (cd crc; make clean) + (cd util; make clean) + (cd fileio; make clean) + (cd macunpack; make clobber) + (cd hexbin; make clobber) + (cd mixed; make clobber) + (cd binhex; make clobber) + (cd comm; make clobber) + +lint: + (cd macunpack; make CF='$(CF)' lint) + (cd hexbin; make CF='$(CF)' lint) + (cd mixed; make CF='$(CF)' lint) + (cd binhex; make CF='$(CF)' lint) + (cd comm; make CF='$(CF)' lint) + +install: + cp macunpack/macunpack $(BINDIR)/. + cp hexbin/hexbin $(BINDIR)/. + cp mixed/macsave $(BINDIR)/. + cp mixed/macstream $(BINDIR)/. + cp binhex/binhex $(BINDIR)/. + cp comm/tomac $(BINDIR)/. + cp comm/frommac $(BINDIR)/. + +distr: + shar -a README makefile crc util fileio macunpack hexbin mixed binhex \ + comm doc man >macutil.shar + diff --git a/man/binhex.1 b/man/binhex.1 new file mode 100755 index 0000000..947ee9c --- /dev/null +++ b/man/binhex.1 @@ -0,0 +1,104 @@ +.TH BINHEX L "October 22, 1992" +.UC +.SH NAME +binhex \- Hexifies a series of files +.SH SYNOPSIS +.B binhex +[ +.B \- options +] [ files ] +.br +.SH DESCRIPTION +.I binhex +takes the files specified in +.I files +and hexifies them in BinHex 4.0 format on standard output +subject to the +.I options +specified. +If +.I files +also specifies directories they are followed recursively, and all files +found will be hexified. +If no +.I files +parameter is specified, binhex reads a MacBinary stream from standard +input and hexifies the files found; folder information is lost. +.SH OPTIONS +In the absence of any options, +.I binhex +takes the specified files and silently hexifies them to BinHex 4.0 +format, writing the result to standard output. +Directories named in +.I files +are followed recursively, all files found will be hexified. +Files are assumed to be in MacBinary format. +However, if the filename ends with .info the file is assumed to be +the info fork of a MacIntosh file split amongst more than one file. +In that case the files with .data and .rsrc extensions +are also read (if present). +Also, if the info fork is mentioned in the parameter list, the names +of data and resource forks can also be mentioned, but those will be +ignored (this is to allow wild-card expansion by the shell.) +Further, if some form of AppleShare is supported by the installed +program, and if the current directory, or one of the directories found +during recursive processing, is a directory in the format of the +supported version of AppleShare, those files will be handled according +to the properties of AppleShare. +.TP +.B \-r +No intelligent file-processing is performed; all files named are assumed +to be plain resource files, and are hexified as if they were +MacIntosh resource files with +creator "RSED" and type "RSRC", unless another creator and/or type are +specified. +.TP +.B \-d +No intelligent file-processing is performed; all files named are assumed +to be plain data files, and are hexified as if they were +MacIntosh data files with +creator "MACA" and type "TEXT", unless another creator and/or type are +specified. +.TP +.B \-u +As -d, but the codes for CR and LF are interchanged. +.TP +.B \-U +Is a synonym for -u. +.TP +.B \-c creator +Defines the creator name to be used if one of the previous options is +specified. +.TP +.B \-t type +Defines the type name to be used if one of the previous options is +specified. +.TP +.B \-R +Do not use run-length encoding during the conversion. +This option may speed up the encoding a bit, but it is merely a +historical artifact. +.TP +.B \-l +List every file and directory processed. +.TP +.B \-i +Do not output files, give information only (implies -l.) +.TP +.B \-q +Ask the user for every file/directory whether it should be visited +(implies -l.) +.TP +.B \-V +Gives the patchlevel of the program, and other information. +Other options are ignored and the program quits immediately. +.TP +.B \-H +Give short information about the options. +Other options are ignored and the program quits immediately. +.SH BUGS +As this is a beta release, there may still be some problems. +.SH SEE ALSO +macutil(1) +.SH AUTHOR +Dik T. Winter, CWI, Amsterdam, The Netherlands (dik@cwi.nl) diff --git a/man/frommac.1 b/man/frommac.1 new file mode 100755 index 0000000..1d435dc --- /dev/null +++ b/man/frommac.1 @@ -0,0 +1,99 @@ +.TH FROMMAC L "October 22, 1992" +.UC +.SH NAME +frommac \- Receive files from the Macintosh +.SH SYNOPSIS +.B frommac +[ +.B \- options +] +.br +.SH DESCRIPTION +.I frommac +receives files from the Macintosh and processes them +subject to the +.I options +specified. +.SH OPTIONS +In the absence of any options, +.I frommac +receives a single file and stores it +in MacBinary format, giving the output file ".bin" extensions and +placing it in the current working directory. +.TP +.B \-3 +Write files in fork format (.info, .data and .rsrc files.) +.TP +.B \-f +As -3, but empty data and rsrc files are not created. +.TP +.B \-r +Write resource forks only (.rsrc files.) +.TP +.B \-d +Write data forks only (.data files.) +.TP +.B \-u +As -d, but the codes for CR and LF are interchanged, the filename extension +is .text. +.TP +.B \-U +As -u, but there is no filename extension. +.TP +.B \-a +Write files in AppleShare format. +This option is only valid if the program is compiled with support +for some form of AppleShare. +The current directory must be a valid AppleShare folder. +.TP +.B \-s +Write received files to standard output in MacBinary format. +.TP +.B \-l +List every file received. +.TP +.B \-m +Receive multiple files. +Entering ^X (CNTRL-X) after the last file will terminate the program. +.TP +.B \-x +Use the XMODEM protocol for transmission. +.TP +.B \-y +Use the YMODEM protocol for transmission (not yet supported.) +.TP +.B \-z +Use the ZMODEM protocol for transmission (not yet supported.) +.TP +.B \-o +Use the pre-beta version of XMODEM. +.TP +.B \-T +Allow for time-out detection during the protocol. +Normally you will not need this option because on occasion, when network +delays do occur, time-out detection interferes with a good transmission. +Also, when for some reason the connection is broken the program will +normally receive a hang-up signal and terminate. +However, in some situations it might be necessary to early detect time-outs +(because of communication loss or whatever, without loss of connection). +You should check whether use of this option has profits in your situation +or not. +Normally when transmission errors did occur entering a number of times +^X (CNTRL-X) will gracefully terminate the program. +.TP +.B \-V +Gives the patchlevel of the program, and other information. +Other options are ignored and the program quits immediately. +.TP +.B \-H +Give short information about the options. +Other options are ignored and the program quits immediately. +.SH BUGS +As this is a beta release, there may still be some problems. +.SH SEE ALSO +macutil(1) +.SH AUTHOR +Dik T. Winter, CWI, Amsterdam, The Netherlands (dik@cwi.nl) +.sp 1 +Parts of the code are based on codes from: +Dave Johnson. diff --git a/man/hexbin.1 b/man/hexbin.1 new file mode 100755 index 0000000..04041cb --- /dev/null +++ b/man/hexbin.1 @@ -0,0 +1,106 @@ +.TH HEXBIN L "October 22, 1992" +.UC +.SH NAME +hexbin \- Macintosh file de-binhexer +.SH SYNOPSIS +.B hexbin +[ +.B \- options +] [ files ] +.br +.SH DESCRIPTION +.I hexbin +takes the text files specified in +.I files +(or standard input if none is specified) and converts them +subject to the +.I options +specified. +.SH OPTIONS +In the absence of any options, +.I hexbin +takes the specified files and silently converts them +into MacBinary format, giving the output files ".bin" extensions and +placing them in the current working directory. +.TP +.B \-3 +Write files in fork format (.info, .data and .rsrc files.) +.TP +.B \-f +As -3, but empty data and rsrc files are not created. +.TP +.B \-r +Write resource forks only (.rsrc files.) +.TP +.B \-d +Write data forks only (.data files.) +.TP +.B \-u +As -d, but the codes for CR and LF are interchanged, the filename extension +is .text. +.TP +.B \-U +As -u, but there is no filename extension. +.TP +.B \-a +Write files in AppleShare format. +This option is only valid if the program is compiled with support +for some form of AppleShare. +The current directory must be a valid AppleShare folder. +.TP +.B \-s +Write extracted files to standard output in MacBinary format. +.TP +.B \-l +List every file extracted (and every directory/folder created etc.) +.TP +.B \-v +Like -l, but more verbose. +When this option is specified all lines skipped because they do not +belong to the hexified format are listed (implies -l.) +.TP +.B \-i +Do not convert, give information only (implies -l.) +.TP +.B \-c +Do not check whether the hexified lines have equal size. +Normally the hexifiers gives text files with equal length line size, +hexbin uses this in its heuristics to determine whether a line must +be skipped. +There are however hexified files that do not conform to that pattern. +If this option is specified hexbin will in general be unable to detect +whether a line is garbage or not, so you have to remove the garbage by +hand. +.TP +.B \-n name +Gives the Unix base file name for the converted files. +For files hexified with BinHex 4.0 or compatible hexifiers this flag +is not needed; hexbin will determine the Unix file name based on the +Mac file name. +For files in dl, hex or hcx format this parameter may be needed as +these formats do not include the Mac filename. +Normally hexbin will in those cases base the Unix file name on the +text file name, but that can be overruled with this parameter. +.TP +.B \-V +Gives the patchlevel of the program, and other information. +Other options are ignored and the program quits immediately. +.TP +.B \-H +Give short information about the options. +Other options are ignored and the program quits immediately. +.SH BUGS +As this is a beta release, there may still be some problems. +.SH SEE ALSO +macutil(1) +.SH AUTHOR +Dik T. Winter, CWI, Amsterdam, The Netherlands (dik@cwi.nl) +.sp 1 +Parts of the code are based on codes from: +ahm (?), +Darin Adler, +Jim Budler, +Dave Johnson, +Dan LaLiberte, +Jeff Meyer, +Guido van Rossum. diff --git a/man/macsave.1 b/man/macsave.1 new file mode 100755 index 0000000..2e946ac --- /dev/null +++ b/man/macsave.1 @@ -0,0 +1,78 @@ +.TH MACSAVE L "October 22, 1992" +.UC +.SH NAME +macsave \- Save Mac files read from standard input +.SH SYNOPSIS +.B macsave +[ +.B \- options +] +.br +.SH DESCRIPTION +.I macsave +reads a sequence of Macintosh MacBinary files from standard input and writes +the files it contains subject to the +.I options +specified. +.SH OPTIONS +In the absence of any options, +.I macsave +reads standard input and silently writes the file(s) it contains +in MacBinary format, giving the output files ".bin" extensions and +placing them in the current working directory. +Subdirectories are created for embedded folders. +.TP +.B \-3 +Write files in fork format (.info, .data and .rsrc files.) +.TP +.B \-f +As -3, but empty data and rsrc files are not created. +.TP +.B \-r +Write resource forks only (.rsrc files.) +.TP +.B \-d +Write data forks only (.data files.) +.TP +.B \-u +As -d, but the codes for CR and LF are interchanged, the filename extension +is .text. +.TP +.B \-U +As -u, but there is no filename extension. +.TP +.B \-a +Write files in AppleShare format. +This option is only valid if the program is compiled with support +for some form of AppleShare. +The current directory must be a valid AppleShare folder. +.TP +.B \-s +Write extracted files to standard output in MacBinary format. +.TP +.B \-l +List every file extracted (and every directory/folder created etc.) +.TP +.B \-v +Like -l, but more verbose (implies -l.) +.TP +.B \-i +Do not extract, give information only (implies -l.) +.TP +.B \-q +Ask the user for every file/folder whether it should be extracted +(implies -l.) +.TP +.B \-V +Gives the patchlevel of the program, and other information. +Other options are ignored and the program quits immediately. +.TP +.B \-H +Give short information about the options. +Other options are ignored and the program quits immediately. +.SH BUGS +As this is a beta release, there may still be some problems. +.SH SEE ALSO +macutil(1) +.SH AUTHOR +Dik T. Winter, CWI, Amsterdam, The Netherlands (dik@cwi.nl) diff --git a/man/macstream.1 b/man/macstream.1 new file mode 100755 index 0000000..ca8d360 --- /dev/null +++ b/man/macstream.1 @@ -0,0 +1,95 @@ +.TH MACSTREAM L "October 22, 1992" +.UC +.SH NAME +macstream \- Convert a series of files to a MacBinary stream +.SH SYNOPSIS +.B macstream +[ +.B \- options +] files +.br +.SH DESCRIPTION +.I macstream +takes the files specified in +.I files +and combines them to a MacBinary stream on standard output +subject to the +.I options +specified. +If +.I files +also specifies directories they are followed recursively, and all files +found will be put in the MacBinary stream, together with directory +information. +.SH OPTIONS +In the absence of any options, +.I macstream +takes the specified files and silently combines them +to a MacBinary stream, writing the result to standard output. +Directories named in +.I files +are followed recursively, all files found will be put in the MacBinary +stream, together with directory information. +Files are assumed to be in MacBinary format. +However, if the filename ends with .info the file is assumed to be +the info fork of a MacIntosh file split amongst more than one file. +In that case the files with .data and .rsrc extension +are also read (if present). +Also, if the info fork is mentioned in the parameter list, the names +of data and resource forks can also be mentioned, but those will be +ignored (this is to allow wild-card expansion by the shell.) +Further, if some form of AppleShare is supported by the installed +program, and if the current directory, or one of the directories found +during recursive processing, is a directory in the format of the +supported version of AppleShare, those files will be handled according +to the properties of AppleShare. +.TP +.B \-r +No intelligent file-processing is performed; all files named are assumed +to be plain resource files, and are written as MacIntosh resource files with +creator "RSED" and type "RSRC", unless another creator and/or type are +specified. +.TP +.B \-d +No intelligent file-processing is performed; all files named are assumed +to be plain data files, and are written as MacIntosh data files with +creator "MACA" and type "TEXT", unless another creator and/or type are +specified. +.TP +.B \-u +As -d, but the codes for CR and LF are interchanged. +.TP +.B \-U +Is a synonym for -u. +.TP +.B \-c creator +Defines the creator name to be used if one of the previous options is +specified. +.TP +.B \-t type +Defines the type name to be used if one of the previous options is +specified. +.TP +.B \-l +List every file and directory processed. +.TP +.B \-i +Do not output files, give information only (implies -l.) +.TP +.B \-q +Ask the user for every file/directory whether it should be visited +(implies -l.) +.TP +.B \-V +Gives the patchlevel of the program, and other information. +Other options are ignored and the program quits immediately. +.TP +.B \-H +Give short information about the options. +Other options are ignored and the program quits immediately. +.SH BUGS +As this is a beta release, there may still be some problems. +.SH SEE ALSO +macutil(1) +.SH AUTHOR +Dik T. Winter, CWI, Amsterdam, The Netherlands (dik@cwi.nl) diff --git a/man/macunpack.1 b/man/macunpack.1 new file mode 100755 index 0000000..696256a --- /dev/null +++ b/man/macunpack.1 @@ -0,0 +1,100 @@ +.TH MACUNPACK L "October 22, 1992" +.UC +.SH NAME +macunpack \- Macintosh file de-archiver +.SH SYNOPSIS +.B macunpack +[ +.B \- options +] [ file ] +.br +.SH DESCRIPTION +.I macunpack +takes the Macintosh MacBinary archive specified in +.I file +(or standard input if none is specified) and extracts the files it +contains subject to the +.I options +specified. +The program will also accept the data fork of the archive for some kinds +of archive as standard input. +.SH OPTIONS +In the absence of any options, +.I macunpack +takes the specified archive and silently extracts the file(s) it contains +into MacBinary format, giving the output files ".bin" extensions and +placing them in the current working directory. +Subdirectories are created for embedded folders. +.TP +.B \-3 +Write files in fork format (.info, .data and .rsrc files.) +.TP +.B \-f +As -3, but empty data and rsrc files are not created. +.TP +.B \-r +Write resource forks only (.rsrc files.) +.TP +.B \-d +Write data forks only (.data files.) +.TP +.B \-u +As -d, but the codes for CR and LF are interchanged, the filename extension +is .text. +.TP +.B \-U +As -u, but there is no filename extension. +.TP +.B \-a +Write files in AppleShare format. +This option is only valid if the program is compiled with support +for some form of AppleShare. +The current directory must be a valid AppleShare folder. +.TP +.B \-s +Write extracted files to standard output in MacBinary format. +.TP +.B \-l +List every file extracted (and every directory/folder created etc.) +.TP +.B \-v +Like -l, but more verbose (implies -l.) +.TP +.B \-i +Do not extract, give information only (implies -l.) +.TP +.B \-q +Ask the user for every file/folder whether it should be extracted +(implies -l.) +.TP +.B \-V +Gives the patchlevel of the program, and other information. +Other options are ignored and the program quits immediately. +.TP +.B \-H +Give short information about the options. +Other options are ignored and the program quits immediately. +.SH BUGS +As this is a beta release, there may still be some problems. Archives +that are password protected and multi-file archives +are not dealt with. +.SH SEE ALSO +macutil(1) +.SH AUTHOR +Dik T. Winter, CWI, Amsterdam, The Netherlands (dik@cwi.nl) +.sp 1 +Parts of the code are based on codes from: +Steve Davies, +Rahul Dhesi, +Casper H.S. Dik, +Jim McKie, +Mark G. Mendel, +Haruhiko Okumura, +Joe Orost, +Samuel H. Smith, +Yooichi Tagawa, +Spencer W. Thomas, +Ken Turkowski, +Allan G. Weber, +James A. Woods and +Haruyasu Yoshizaki. diff --git a/man/macutil.1 b/man/macutil.1 new file mode 100755 index 0000000..bcce0b7 --- /dev/null +++ b/man/macutil.1 @@ -0,0 +1,42 @@ +.TH MACUTIL L "October 22, 1992" +.UC +.SH NAME +macutil \- A package that deals with MacIntosh files on a Unix system +.SH DESCRIPTION +.I macutil +is a package that contains a number of utilities that deal with MacIntosh +files on a Unix system. +It contains the following programs: +.TP +.B binhex +Convert files to BinHex 4.0 compatible hexified form. +.TP +.B frommac +Receives files from the MacIntosh on the Unix system. +.TP +.B hexbin +Convert hexified files to their MacIntosh format. +.TP +.B macsave +Save a series of files from a MacBinary stream as individual files. +.TP +.B macstream +Combine a series of files to a MacBinary stream. +.TP +.B macunpack +Unpack a MacIntosh archive into its constituents. +.TP +.B tomac +Transmits files from the Unix system to a MacIntosh. +.SH BUGS +This manual page is hopelessly incomplete! +.SH SEE ALSO +binhex(1), +frommac(1), +hexbin(1), +macsave(1), +macstream(1), +macunpack(1), +tomac(1) +.SH AUTHOR +Dik T. Winter, CWI, Amsterdam, The Netherlands (dik@cwi.nl) diff --git a/man/tomac.1 b/man/tomac.1 new file mode 100755 index 0000000..1b52a45 --- /dev/null +++ b/man/tomac.1 @@ -0,0 +1,124 @@ +.TH TOMAC L "October 22, 1992" +.UC +.SH NAME +tomac \- Transmit files to the Mac +.SH SYNOPSIS +.B tomac +[ +.B \- options +] [ files ] +.br +.SH DESCRIPTION +.I tomac +takes the files specified in +.I tomac +and transmits them to the Mac subject to the +.I options +specified. +If +.I files +also specifies directories they are followed recursively, and all files +found will be transmitted. +If no +.I files +parameter is specified, binhex reads a MacBinary stream from standard +input and transmits the files found; folder information is lost. +.SH OPTIONS +In the absence of any options, +.I tomac +takes the specified files and transmits them to to the Mac using the +XMODEM protocol. +Directories named in +.I files +are followed recursively, all files found will be transmitted. +Files are assumed to be in MacBinary format. +However, if the filename ends with .info the file is assumed to be +the info fork of a MacIntosh file split amongst more than one file. +In that case the files with .data and .rsrc extensions +are also read (if present). +Also, if the info fork is mentioned in the parameter list, the names +of data and resource forks can also be mentioned, but those will be +ignored (this is to allow wild-card expansion by the shell.) +Further, if some form of AppleShare is supported by the installed +program, and if the current directory, or one of the directories found +during recursive processing, is a directory in the format of the +supported version of AppleShare, those files will be handled according +to the properties of AppleShare. +.TP +.B \-r +No intelligent file-processing is performed; all files named are assumed +to be plain resource files, and are transmitted as if they were +MacIntosh resource files with +creator "RSED" and type "RSRC", unless another creator and/or type are +specified. +.TP +.B \-d +No intelligent file-processing is performed; all files named are assumed +to be plain data files, and are transmitted as if they were +MacIntosh data files with +creator "MACA" and type "TEXT", unless another creator and/or type are +specified. +.TP +.B \-u +As -d, but the codes for CR and LF are interchanged. +.TP +.B \-U +Is a synonym for -u. +.TP +.B \-c creator +Defines the creator name to be used if one of the previous options is +specified. +.TP +.B \-t type +Defines the type name to be used if one of the previous options is +specified. +.TP +.B \-l +List every file and directory processed. +.TP +.B \-i +Do not transmit files, give information only (implies -l.) +.TP +.B \-q +Ask the user for every file/directory whether it should be visited +(implies -l.) +.TP +.B \-x +Use the XMODEM protocol for transmission. +.TP +.B \-y +Use the YMODEM protocol for transmission (not yet supported.) +.TP +.B \-z +Use the ZMODEM protocol for transmission (not yet supported.) +.TP +.B \-o +Use the pre-beta version of XMODEM. +.TP +.B \-T +Allow for time-out detection during the protocol. +Normally you will not need this option because on occasion, when network +delays do occur, time-out detection interferes with a good transmission. +Also, when for some reason the connection is broken the program will +normally receive a hang-up signal and terminate. +However, in some situations it might be necessary to early detect time-outs +(because of communication loss or whatever, without loss of connection). +You should check whether use of this option has profits in your situation +or not. +.TP +.B \-V +Gives the patchlevel of the program, and other information. +Other options are ignored and the program quits immediately. +.TP +.B \-H +Give short information about the options. +Other options are ignored and the program quits immediately. +.SH BUGS +As this is a beta release, there may still be some problems. +.SH SEE ALSO +macutil(1) +.SH AUTHOR +Dik T. Winter, CWI, Amsterdam, The Netherlands (dik@cwi.nl) +.sp 1 +Parts of the code are based on codes from: +Dave Johnson. diff --git a/mixed/dir.c b/mixed/dir.c new file mode 100755 index 0000000..494b395 --- /dev/null +++ b/mixed/dir.c @@ -0,0 +1,75 @@ +#include "globals.h" +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "../util/util.h" +#include "../util/masks.h" + +extern char *malloc(); +extern char *realloc(); + +static char *dir_stack; +static int dir_ptr = -64; +static int dir_max; + +void dir(hdr) +char *hdr; +{ +int doit; + + if((hdr[I_NAMEOFF] & BYTEMASK) == 0x80) { + if(dir_skip) { + dir_skip--; + return; + } + indent--; + if(list) { + do_indent(indent); + (void)fprintf(stderr, "leaving folder \"%s\"\n", + dir_stack + dir_ptr); + } + if(!info_only) { + enddir(); + } + dir_ptr -= 64; + return; + } + if(dir_skip) { + dir_skip++; + return; + } + dir_ptr += 64; + if(dir_ptr == dir_max) { + if(dir_max == 0) { + dir_stack = malloc(64); + } else { + dir_stack = realloc(dir_stack, (unsigned)dir_max + 64); + } + dir_max += 64; + if(dir_stack == NULL) { + (void)fprintf(stderr, "Insufficient memory\n"); + exit(1); + } + } + transname(hdr + I_NAMEOFF + 1, dir_stack + dir_ptr, + (int)(hdr[I_NAMEOFF] & 0x7f)); + doit = 1; + if(list) { + do_indent(indent); + (void)fprintf(stderr, "folder=\"%s\"", dir_stack + dir_ptr); + if(query) { + doit = do_query(); + } else { + (void)fputc('\n', stderr); + } + } + if(!doit) { + dir_ptr -= 64; + dir_skip = 1; + return; + } + if(!info_only) { + do_mkdir(dir_stack + dir_ptr, hdr); + } + indent++; +} + diff --git a/mixed/globals.c b/mixed/globals.c new file mode 100755 index 0000000..da9e076 --- /dev/null +++ b/mixed/globals.c @@ -0,0 +1,12 @@ +#include "globals.h" +#include "../fileio/machdr.h" + +char info[INFOBYTES]; +char text[F_NAMELEN+1]; + +int list, info_only, query, write_it, indent, dir_skip; +FILE *infp; +int in_data_size = -1; +int in_rsrc_size = -1; +int in_ds, in_rs, ds_skip, rs_skip; + diff --git a/mixed/globals.h b/mixed/globals.h new file mode 100755 index 0000000..6c058e8 --- /dev/null +++ b/mixed/globals.h @@ -0,0 +1,13 @@ +#include + +extern void exit(); +extern void transname(); + +extern char info[]; +extern char text[]; + +extern int list, info_only, query, write_it, indent, dir_skip; +extern FILE *infp; + +extern int in_data_size, in_rsrc_size, in_ds, in_rs, ds_skip, rs_skip; + diff --git a/mixed/macbinary.c b/mixed/macbinary.c new file mode 100755 index 0000000..5bf6bfd --- /dev/null +++ b/mixed/macbinary.c @@ -0,0 +1,121 @@ +#include "globals.h" +#include "../fileio/machdr.h" +#include "../fileio/kind.h" +#include "../util/util.h" + +extern void dir(); +extern void mcb(); +extern void do_indent(); + +static void skip_file(); +#ifdef SCAN +static void get_idf(); +#endif /* SCAN */ + +void macbinary() +{ + char header[INFOBYTES]; + int c; + + while(1) { + if((c = fgetc(infp)) == EOF) { + break; + } + (void)ungetc(c, infp); + if(fread(header, 1, INFOBYTES, infp) != INFOBYTES) { + (void)fprintf(stderr, "Can't read MacBinary header.\n"); + exit(1); + } + if(header[I_NAMEOFF] & 0x80) { + dir(header); + continue; + } + in_data_size = get4(header + I_DLENOFF); + in_rsrc_size = get4(header + I_RLENOFF); + in_ds = (((in_data_size + 127) >> 7) << 7); + in_rs = (((in_rsrc_size + 127) >> 7) << 7); + ds_skip = in_ds - in_data_size; + rs_skip = in_rs - in_rsrc_size; + if(dir_skip != 0) { + skip_file(in_ds + in_rs); + continue; + } +#ifdef SCAN + if(header[I_NAMEOFF] == 0) { + get_idf((int)header[I_NAMEOFF + 1]); + skip_file(ds_skip + in_rs); + continue; + } +#endif /* SCAN */ + if(header[0] == 0 /* MORE CHECKS HERE! */) { + mcb(header, (unsigned long)in_rsrc_size, + (unsigned long)in_data_size, in_ds + in_rs); + continue; + } else { + (void)fprintf(stderr, "Unrecognized header.\n"); + exit(1); + } + } +} + +static void skip_file(skip) + int skip; +{ + char buff[1024]; + int n; + + while(skip > 0) { + n = (skip < 1024 ? skip : 1024); + if(fread(buff, 1, n, infp) != n) { + (void)fprintf(stderr, "Incomplete file.\n"); + exit(1); + } + skip -= n; + } +} + +#ifdef SCAN +static void get_idf(kind) + int kind; +{ + char filename[1024], filename1[255]; + + if(fread(filename, 1, in_data_size, infp) != in_data_size) { + (void)fprintf(stderr, "Incomplete file.\n"); + exit(1); + } + filename[in_data_size] = 0; + if(list) { + do_indent(indent); + switch(kind) { + case UNIX_NAME: + (void)fprintf(stderr, "Unix filename: \"%s\"\n", filename); + break; + case PACK_NAME: + transname(filename, filename1, in_data_size); + (void)fprintf(stderr, "Packed filename: \"%s\"\n", filename1); + break; + case ARCH_NAME: + transname(filename, filename1, in_data_size); + (void)fprintf(stderr, "Archive name: \"%s\"\n", filename1); + break; + case UNKNOWN: + (void)fprintf(stderr, "Unknown method detected\n"); + break; + case ERROR: + (void)fprintf(stderr, "Error detected\n"); + break; + case PROTECTED: + (void)fprintf(stderr, "Protected file detected\n"); + break; + case COPY: + (void)fprintf(stderr, "Copied file found\n"); + break; + default: + (void)fprintf(stderr, "Do not understand this identification\n"); + exit(1); + } + } +} +#endif /* SCAN */ + diff --git a/mixed/macsave.c b/mixed/macsave.c new file mode 100755 index 0000000..5fa797a --- /dev/null +++ b/mixed/macsave.c @@ -0,0 +1,96 @@ +#include "globals.h" +#include "../util/patchlevel.h" +#include "../fileio/wrfile.h" +#include "../fileio/wrfileopt.h" +#include "../util/util.h" + +#define LOCALOPT "ilqVH" + +extern char *strcat(); +void macbinary(); + +static void usage(); + +static char options[128]; + +int main(argc, argv) +int argc; +char *argv[]; +{ + int c; + extern int optind; + extern char *optarg; + int errflg; + + set_wrfileopt(0); + set_s_wrfileopt(1); + (void)strcat(options, get_wrfileopt()); + (void)strcat(options, LOCALOPT); + errflg = 0; + + while((c = getopt(argc, argv, options)) != EOF) { + if(!wrfileopt((char)c)) { + switch(c) { + case 'l': + list++; + break; + case 'q': + query++; + break; + case 'i': + info_only++; + break; + case '?': + errflg++; + break; + case 'H': + give_wrfileopt(); + (void)fprintf(stderr, "Macsave specific options:\n"); + (void)fprintf(stderr, + "-i:\tgive information only, do not save\n"); + (void)fprintf(stderr, "-l:\tgive listing\n"); + (void)fprintf(stderr, + "-q:\tquery for every file/folder before saving\n"); + (void)fprintf(stderr, + "-V:\tgive information about this version\n"); + (void)fprintf(stderr, "-H:\tthis message\n"); + (void)fprintf(stderr, "Default is silent saving\n"); + exit(0); + case 'V': + (void)fprintf(stderr, "Version %s, ", VERSION); + (void)fprintf(stderr, "patchlevel %d", PATCHLEVEL); + (void)fprintf(stderr, "%s.\n", get_mina()); + exit(0); + } + } + } + if(errflg || optind != argc) { + usage(); + exit(1); + } + + infp = stdin; + + if(info_only || query) { + list++; + } + c = getc(infp); + (void)ungetc(c, infp); + switch(c) { + case 0: + macbinary(); + break; + default: + (void)fprintf(stderr, "Input is not MacBinary\n"); + exit(1); + } + exit(0); + /* NOTREACHED */ +} + +static void usage() +{ + (void)fprintf(stderr, "Usage: macsave [-%s]\n", options); + (void)fprintf(stderr, "Use \"macsave -H\" for help.\n"); +} + diff --git a/mixed/macstream.c b/mixed/macstream.c new file mode 100755 index 0000000..a9b61aa --- /dev/null +++ b/mixed/macstream.c @@ -0,0 +1,183 @@ +#include +#include "../fileio/machdr.h" +#include "../fileio/rdfile.h" +#include "../fileio/rdfileopt.h" +#include "../util/patchlevel.h" + +extern char *malloc(); +extern char *realloc(); +extern char *strcat(); +extern void exit(); +extern void transname(); +extern void do_indent(); + +#define LOCALOPT "ilqVH" + +static void usage(); + +static char options[128]; +static char *dir_stack; +static int dir_ptr = -64; +static int dir_max; + +int main(argc, argv) +int argc; +char **argv; +{ + int c, i, j, n; + extern int optind; + extern char *optarg; + int errflg; + char text[32], ftype[5], fauth[5]; + int dir_skip = 0, write_it, query = 0, list = 0, info_only = 0; + int indent = 0; + + (void)strcat(options, get_rdfileopt()); + (void)strcat(options, LOCALOPT); + errflg = 0; + + while((c = getopt(argc, argv, options)) != EOF) { + if(!rdfileopt((char)c)) { + switch(c) { + case 'l': + list++; + break; + case 'q': + query++; + break; + case 'i': + info_only++; + break; + case '?': + errflg++; + break; + case 'H': + give_rdfileopt(); + (void)fprintf(stderr, "Macstream specific options:\n"); + (void)fprintf(stderr, + "-i:\tgive information only, do not write\n"); + (void)fprintf(stderr, "-l:\tgive listing\n"); + (void)fprintf(stderr, + "-q:\tquery for every file/folder before writing\n"); + (void)fprintf(stderr, + "-V:\tgive information about this version\n"); + (void)fprintf(stderr, "-H:\tthis message\n"); + (void)fprintf(stderr, "Default is silent writing\n"); + exit(0); + case 'V': + (void)fprintf(stderr, "Version %s, ", VERSION); + (void)fprintf(stderr, "patchlevel %d", PATCHLEVEL); + (void)fprintf(stderr, "%s.\n", get_minb()); + exit(0); + } + } + } + if(errflg || optind == argc) { + usage(); + exit(1); + } + + if(info_only || query) { + list++; + } + + setup(argc - optind, argv + optind); + while((i = nextfile()) != ISATEND) { + if(dir_skip) { + if(i == ISDIR) { + dir_skip++; + } else if(i == ENDDIR) { + dir_skip--; + } + continue; + } + + write_it = 1; + n = file_info[I_NAMEOFF] & 0x7f; + transname(file_info + I_NAMEOFF + 1, text, n); + if(i == ISFILE) { + transname(file_info + I_TYPEOFF, ftype, 4); + transname(file_info + I_AUTHOFF, fauth, 4); + } + if(list) { + if(i == ISFILE) { + do_indent(indent); + (void)fprintf(stderr, + "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld", + text, ftype, fauth, (long)data_size, (long)rsrc_size); + } else if(i == ISDIR) { + do_indent(indent); + dir_ptr += 64; + if(dir_ptr == dir_max) { + if(dir_max == 0) { + dir_stack = malloc(64); + } else { + dir_stack = realloc(dir_stack, (unsigned)dir_max + 64); + } + dir_max += 64; + if(dir_stack == NULL) { + (void)fprintf(stderr, "Insufficient memory\n"); + exit(1); + } + } + for(j = 0; j <= n; j++) { + dir_stack[dir_ptr + j] = text[j]; + } + (void)fprintf(stderr, "folder=\"%s\"", text); + indent++; + } else { + indent--; + do_indent(indent); + (void)fprintf(stderr, "leaving folder \"%s\"", + dir_stack + dir_ptr); + dir_ptr -= 64; + } + if(info_only) { + write_it = 0; + } + if(query) { + if(i != ENDDIR) { + write_it = do_query(); + } else { + (void)fputc('\n', stderr); + } + if(!write_it && i == ISDIR) { + dir_skip = 1; + indent--; + dir_ptr -= 64; + } + } else { + (void)fputc('\n', stderr); + } + } + + if(write_it) { + (void)fwrite(file_info, 1, 128, stdout); + if(i == ISFILE) { + if(data_size != 0) { + (void)fwrite(data_fork, 1, data_size, stdout); + i = (((data_size + 127) >> 7) << 7) - data_size; + while(i-- > 0) { + (void)fputc(0, stdout); + } + } + if(rsrc_size != 0) { + (void)fwrite(rsrc_fork, 1, rsrc_size, stdout); + i = (((rsrc_size + 127) >> 7) << 7) - rsrc_size; + while(i-- > 0) { + (void)fputc(0, stdout); + } + } + } + } + } + exit(0); + /* NOTREACHED */ +} + +static void usage() +{ + (void)fprintf(stderr, "Usage: macstream [-%s] files\n", options); + (void)fprintf(stderr, "Use \"macstream -H\" for help.\n"); +} + diff --git a/mixed/makefile b/mixed/makefile new file mode 100755 index 0000000..5a887bb --- /dev/null +++ b/mixed/makefile @@ -0,0 +1,92 @@ +CFLAGS = -O $(CF) + +SRCS1 = macsave.c \ + globals.c \ + macbinary.c \ + dir.c \ + mcb.c + +SRCS2 = macstream.c + +OBJS1 = macsave.o \ + globals.o \ + macbinary.o \ + dir.o \ + mcb.o + +OBJS2 = macstream.o + +TNAME = ../util/transname +BNAME = ../util/backtrans +UNAME = ../util/util +ONAME = ../fileio/wrfile +INAME = ../fileio/rdfile +GNAME = ../fileio/fileglob +XOBJS1= $(TNAME).o $(UNAME).o $(ONAME).o $(GNAME).o +XSRCS1= $(TNAME).c $(UNAME).c $(ONAME).c $(GNAME).c +XOBJS2= $(TNAME).o $(BNAME).o $(UNAME).o $(INAME).o $(GNAME).o +XSRCS2= $(TNAME).c $(BNAME).c $(UNAME).c $(INAME).c $(GNAME).c + +all: macsave macstream + touch all + +macsave: $(OBJS1) $(XOBJS1) + $(CC) $(CFLAGS) -o macsave $(OBJS1) $(XOBJS1) + +macstream: $(OBJS2) $(XOBJS2) + $(CC) $(CFLAGS) -o macstream $(OBJS2) $(XOBJS2) + +$(TNAME).o: $(TNAME).c + (cd ../util; make CC=$(CC) CF="$(CF)" ) + +$(BNAME).o: $(BNAME).c + (cd ../util; make CC=$(CC) CF="$(CF)" ) + +$(UNAME).o: $(UNAME).c + (cd ../util; make CC=$(CC) CF="$(CF)" ) + +$(ONAME).o: $(ONAME).c + (cd ../fileio; make CC=$(CC) CF="$(CF)" ) + +$(INAME).o: $(INAME).c + (cd ../fileio; make CC=$(CC) CF="$(CF)" ) + +$(GNAME).o: $(GNAME).c + (cd ../fileio; make CC=$(CC) CF="$(CF)" ) + +lint: + lint $(CF) $(LFLAGS) $(SRCS1) $(XSRCS1) + lint $(CF) $(LFLAGS) $(SRCS2) $(XSRCS2) + +clean: + -rm -f *.o + +clobber:clean + -rm -f all macsave macstream + +macsave.o: globals.h +macsave.o: ../util/patchlevel.h +macsave.o: ../fileio/wrfile.h +macsave.o: ../fileio/wrfileopt.h +macsave.o: ../util/util.h +globals.o: globals.h +globals.o: ../fileio/machdr.h +macbinary.o: globals.h +macbinary.o: ../fileio/machdr.h +macbinary.o: ../fileio/kind.h +macbinary.o: ../util/util.h +dir.o: globals.h +dir.o: ../fileio/machdr.h +dir.o: ../fileio/wrfile.h +dir.o: ../util/util.h +dir.o: ../util/masks.h +mcb.o: globals.h +mcb.o: ../fileio/machdr.h +mcb.o: ../fileio/wrfile.h +mcb.o: ../util/masks.h +mcb.o: ../util/util.h +macstream.o: ../fileio/machdr.h +macstream.o: ../fileio/rdfile.h +macstream.o: ../fileio/rdfileopt.h +macstream.o: ../util/patchlevel.h + diff --git a/mixed/mcb.c b/mixed/mcb.c new file mode 100755 index 0000000..51b5987 --- /dev/null +++ b/mixed/mcb.c @@ -0,0 +1,109 @@ +#include "globals.h" +#include "../fileio/machdr.h" +#include "../fileio/wrfile.h" +#include "../util/masks.h" +#include "../util/util.h" + +static int mcb_read; + +static void mcb_wrfile(); + +void mcb(hdr, rsrcLength, dataLength, toread) +char *hdr; +unsigned long rsrcLength, dataLength; +int toread; +{ + register int i; + int n; + char ftype[5], fauth[5]; + + mcb_read = toread; + for(i = 0; i < INFOBYTES; i++) { + info[i] = hdr[i]; + } + + n = hdr[I_NAMEOFF] & BYTEMASK; + if(n > F_NAMELEN) { + n = F_NAMELEN; + } + info[I_NAMEOFF] = n; + transname(hdr + I_NAMEOFF + 1, text, n); + if(hdr[I_LOCKOFF] & 1) { + hdr[I_FLAGOFF + 1] = PROTCT_MASK; + hdr[I_LOCKOFF] &= ~1; + } + + write_it = 1; + if(list) { + transname(hdr + I_TYPEOFF, ftype, 4); + transname(hdr + I_AUTHOFF, fauth, 4); + do_indent(indent); + (void)fprintf(stderr, + "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld", + text, ftype, fauth, (long)dataLength, (long)rsrcLength); + if(info_only) { + write_it = 0; + } + if(query) { + write_it = do_query(); + } else { + (void)fputc('\n', stderr); + } + } + + if(write_it) { + define_name(text); + start_info(info, rsrcLength, dataLength); + start_data(); + } + mcb_wrfile(dataLength); + if(write_it) { + start_rsrc(); + } + mcb_wrfile(rsrcLength); + if(write_it) { + end_file(); + } +} + +static void mcb_wrfile(ibytes) +unsigned long ibytes; +{ + int n; + + if(write_it) { + if(ibytes == 0) { + return; + } + n = fread(out_buffer, 1, (int)ibytes, infp); + if(n != ibytes) { + (void)fprintf(stderr, "Premature EOF\n"); + exit(1); + } + mcb_read -= n; + n = ((n + 127) / 128) * 128 - n; + if(n > mcb_read) { + n = mcb_read; + } + mcb_read -= n; + while(n-- > 0) { + if(getc(infp) == EOF) { + (void)fprintf(stderr, "Premature EOF\n"); + exit(1); + } + } + } else { + n = ((ibytes + 127) / 128) * 128; + if(n > mcb_read) { + n = mcb_read; + } + mcb_read -= n; + while(n-- > 0) { + if(getc(infp) == EOF) { + (void)fprintf(stderr, "Premature EOF\n"); + exit(1); + } + } + } +} + diff --git a/util/all b/util/all new file mode 100644 index 0000000..e69de29 diff --git a/util/backtrans.c b/util/backtrans.c new file mode 100755 index 0000000..fb6dd5d --- /dev/null +++ b/util/backtrans.c @@ -0,0 +1,104 @@ +#include "masks.h" + +/* Map a command line given name to a Mac name. If LATIN1 is not defined + the translation is direct, except that \ is handled special. \\ is + translated to \, \ddd (three digits) is translated to the octal code. + If LATIN1 is defined, special care has been taken with the 8 bit chars + to get a proper mapping, if possible. Note: colon is translated to _. */ +static char char_mapping[] = { + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + ' ', '!', '"', '#', '$', '%', '&', '\'', + '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '_', ';', '<', '=', '>', '?', + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', '{', '|', '}', '~', 0177, + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', +#ifndef LATIN1 + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_'}; +#else /* LATIN1 */ + '_', 0301, 0242, 0243, 0327, 0265, '_', 0244, + 0254, 0251, '_', 0307, 0302, '_', 0250, '_', + 0241, 0261, '_', '_', 0253, '_', 0246, 0245, + '_', '_', '_', 0310, '_', '_', '_', 0300, + 0313, 0207, 0211, 0313, 0200, 0201, 0256, 0202, + 0217, 0203, 0220, 0221, 0223, 0314, 0224, 0225, + '_', 0204, 0230, 0227, 0231, 0233, 0205, '_', + 0257, 0235, 0234, 0236, 0206, '_', '_', 0247, + 0210, 0207, 0211, 0213, 0212, 0214, 0276, 0215, + 0217, 0216, 0220, 0221, 0223, 0222, 0224, 0225, + '_', 0226, 0230, 0227, 0231, 0233, 0232, 0326, + 0277, 0235, 0234, 0236, 0237, '_', '_', 0330}; +#endif /* LATIN1 */ + +void backtrans(macname, name) +char *macname, *name; +{ + char *in, *out; + int c, count = 0; + + out = macname; + for (in = name; *in; in++){ + if(count == 31) { + break; + } + if(*in != '\\') { + *out++ = char_mapping[*in & BYTEMASK]; + count++; + continue; + } + in++; + if(*in == 0) { + break;; + } + if(*in < '0' || *in > '9') { + *out++ = char_mapping[*in & BYTEMASK]; + count++; + continue; + } + c = *in - '0'; + in++; + if(*in < '0' || *in > '9') { + *out++ = c; + count++; + in--; + continue; + } + c = (c << 3) + *in - '0'; + in++; + if(*in < '0' || *in > '9') { + *out++ = c; + count++; + in--; + continue; + } + c = (c << 3) + *in - '0'; + *out++ = c; + count++; + } + *out++ = 0; +} + diff --git a/util/backtrans.o b/util/backtrans.o new file mode 100644 index 0000000..ec3bd44 Binary files /dev/null and b/util/backtrans.o differ diff --git a/util/curtime.h b/util/curtime.h new file mode 100755 index 0000000..f3533ca --- /dev/null +++ b/util/curtime.h @@ -0,0 +1,14 @@ +#ifdef TYPES_H +#include +#endif /* TYPES_H */ + +#ifdef BSD +#include +extern time_t time(); +#else /* BSD */ +#include +#endif /* BSD */ + +/* Mac time of 00:00:00 GMT, Jan 1, 1970 */ +#define TIMEDIFF 0x7c25b080 + diff --git a/util/makefile b/util/makefile new file mode 100755 index 0000000..92647f5 --- /dev/null +++ b/util/makefile @@ -0,0 +1,22 @@ +CFLAGS= -O $(CF) + +all: util.o transname.o backtrans.o + touch all + +util.o: util.c + +transname.o: transname.c + +backtrans.o: backtrans.c + +clean: + -rm -f util.o + -rm -f transname.o + -rm -f backtrans.o + -rm -f all + +util.o: ../fileio/fileglob.h +util.o: masks.h +util.o: util.h +backtrans.o: masks.h + diff --git a/util/masks.h b/util/masks.h new file mode 100755 index 0000000..b812a32 --- /dev/null +++ b/util/masks.h @@ -0,0 +1,4 @@ +#define NIBBLEMASK 0x0000000f +#define BYTEMASK 0x000000ff +#define WORDMASK 0x0000ffff + diff --git a/util/patchlevel.h b/util/patchlevel.h new file mode 100755 index 0000000..4d8bba1 --- /dev/null +++ b/util/patchlevel.h @@ -0,0 +1,3 @@ +#define VERSION "2.0b3 (22-OCT-1992)" +#define PATCHLEVEL 0 + diff --git a/util/transname.c b/util/transname.c new file mode 100755 index 0000000..70f4591 --- /dev/null +++ b/util/transname.c @@ -0,0 +1,109 @@ +#include +#include + +char *strncpy(); + +#ifdef MAXNAMLEN /* 4.2 BSD */ +#define FNAMELEN MAXNAMLEN +#else +#define FNAMELEN DIRSIZ +#endif + +/* Create a Unix file name based on the Mac filename. First off we have + * possible problems with filename sizes (Sys V) and also with allowable + * characters. Mac filename characters can be anything from 1 to 254 (I + * think 0 and 255 are not allowed) with colon disallowed. Unix filenames + * have also a lot of freedom, but cannot contain 0 or '/'. Also on Unix + * non-printable are a trouble (you will never see the filename correctly; + * and it may even lock your terminal with some versions of Unix). + * So first off non-printable characters are mapped to underscore. + * Although there are Unix systems that allow the high order bit set in + * a filename character in all programs, nearly all implementations do not + * allow that, so also characters in the range 0200-0377 are mapped to + * underscore (except as noted below). Some people would also like to + * remap characters that are special to some shells (open brackets, + * asterisks, exclamation point (csh), etc.) I did elect not to do so + * because there is no end. (The previous code disallowed a lot, but not + * the braces that are special to some shells, obviously he was a C-shell user!) + * Characters in the range 0200-0377 are in part accented letters + * (the Swedes, Norwegians and Danes would not agree, but who listens to + * them!); those are mapped to the unaccented version. All other characters + * in this range are mapped to underscore. Note: this is based on the + * Geneva font! + * This stuff is now largely table driven. + * One day I may modify this so that an environment variable may be used + * to define mappings. */ + +static char char_mapping[] = { + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '!', '"', '#', '$', '%', '&', '\'', + '(', ')', '*', '+', ',', '-', '.', '_', + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', ':', ';', '<', '=', '>', '?', + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', '{', '|', '}', '~', '_', +#ifndef LATIN1 + 'A', 'A', 'C', 'E', 'N', 'O', 'U', 'a', + 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e', + 'e', 'e', 'i', 'i', 'i', 'i', 'n', 'o', + 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', 'O', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', 'o', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', 'A', 'A', 'O', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + 'y', '_', '_', '_', '_', '_', '_', '_', +#else /* LATIN1 */ + 0304, 0305, 0307, 0311, 0321, 0326, 0334, 0341, + 0340, 0342, 0344, 0343, 0345, 0347, 0351, 0350, + 0352, 0353, 0355, 0354, 0356, 0357, 0361, 0363, + 0362, 0364, 0366, 0365, 0372, 0371, 0373, 0374, + '_', 0260, 0242, 0243, 0247, 0267, 0266, 0337, + 0256, 0251, '_', 0264, 0250, '_', 0306, 0330, + '_', 0261, '_', '_', 0245, '_', '_', '_', + '_', '_', '_', '_', '_', '_', 0346, 0370, + 0277, 0241, 0254, '_', '_', '_', '_', 0253, + 0273, '_', '_', 0300, 0303, 0325, '_', '_', + '_', '_', '_', '_', '_', '_', 0367, 0244, + 0377, '_', '_', '_', '_', '_', '_', '_', +#endif /* LATIN1 */ + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_', + '_', '_', '_', '_', '_', '_', '_', '_'}; + +void transname(name, namebuf, n) +char *name, *namebuf; +int n; +{ + char *np; + + /* make sure host file name doesn't get truncated beyond recognition */ + if (n > FNAMELEN - 2) { + n = FNAMELEN - 2; + } + (void)strncpy(namebuf, name, n); + namebuf[n] = '\0'; + + /* now: translate name */ + for (np = namebuf; *np; np++){ + *np = char_mapping[*np & 0xff]; + } +#ifdef NODOT + if(*namebuf == '.') { + *namebuf = '_'; + } +#endif /* NODOT */ +} + diff --git a/util/transname.o b/util/transname.o new file mode 100644 index 0000000..a73de2e Binary files /dev/null and b/util/transname.o differ diff --git a/util/util.c b/util/util.c new file mode 100755 index 0000000..29ff425 --- /dev/null +++ b/util/util.c @@ -0,0 +1,209 @@ +#include +#include "../fileio/fileglob.h" +#include "masks.h" +#include "util.h" + +extern void exit(); + +#define MACTIMOFFS 1904 + +static int mlength[] = {0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337}; + +unsigned long get4(bp) +char *bp; +{ + register int i; + long value = 0; + + for(i = 0; i < 4; i++) { + value <<= 8; + value |= (*bp & BYTEMASK); + bp++; + } + return value; +} + +/* For if integers are stored wrong-endian. */ +unsigned long get4i(bp) +char *bp; +{ + register int i; + long value = 0; + + bp += 3; + for(i = 0; i < 4; i++) { + value <<= 8; + value |= (*bp & BYTEMASK); + bp--; + } + return value; +} + +unsigned long get2(bp) +char *bp; +{ + register int i; + int value = 0; + + for(i = 0; i < 2; i++) { + value <<= 8; + value |= (*bp & BYTEMASK); + bp++; + } + return value; +} + +/* For if integers are stored wrong-endian. */ +unsigned long get2i(bp) +char *bp; +{ + register int i; + long value = 0; + + bp += 1; + for(i = 0; i < 2; i++) { + value <<= 8; + value |= (*bp & BYTEMASK); + bp--; + } + return value; +} + +unsigned char getb(fp) +FILE *fp; +{ + int c; + + bytes_read += 1; + c = getc(fp); + if(c == EOF) { + (void)fprintf(stderr, "\nPremature EOF\n"); + exit(1); + } + return c & BYTEMASK; +} + +void copy(d, s, n) +char *d, *s; +int n; +{ + while(--n >= 0) { + *d++ = *s++; + } +} + +int do_query() +{ + char *tp, temp[10]; + + (void)fprintf(stderr, "? "); + (void) fflush(stdout); + (void) read(2, temp, sizeof(temp)); + temp[sizeof(temp) - 1] = 0; + tp = temp; + while(*tp != 0) { + if(*tp == 'y' || *tp == 'Y') { + return 1; + } else { + tp++; + } + } + return 0; +} + +void put4(dest, value) +char *dest; +unsigned long value; +{ + *dest++ = (value >> 24) & BYTEMASK; + *dest++ = (value >> 16) & BYTEMASK; + *dest++ = (value >> 8) & BYTEMASK; + *dest++ = value & BYTEMASK; +} + +void put2(dest, value) +char *dest; +unsigned long value; +{ + *dest++ = (value >> 8) & BYTEMASK; + *dest++ = value & BYTEMASK; +} + +void do_indent(indent) +int indent; +{ + int i; + + for(i = 0; i < indent; i++) { + (void)fputc(' ', stderr); + } +} + +real_time set_time(year, month, day, hours, minutes, seconds) +int year, month, day, hours, minutes, seconds; +{ + real_time toset; + + toset.year = year; + toset.month = month; + toset.day = day; + toset.hours = hours; + toset.minutes = minutes; + toset.seconds = seconds; + return toset; +} + +unsigned long tomactime(time) +real_time time; +{ + long accum; + int year; + + accum = time.month - 3; + year = time.year; + if(accum < 0) { + accum += 12; + year--; + } + accum = time.day + mlength[accum] + 59; + accum += (year - MACTIMOFFS) * 365 + year / 4 - MACTIMOFFS / 4; + accum = ((accum * 24 + time.hours) * 60 + time.minutes) * 60 + time.seconds; + return (unsigned)accum; +} + +real_time frommactime(accum) +unsigned long accum; +{ +long tmp1, tmp2; +real_time time; + + time.seconds = tmp1 = accum % 60; + accum /= 60; + time.minutes = tmp1 = accum % 60; + accum /= 60; + time.hours = tmp1 = accum % 24; + accum /= 24; + tmp1 = (long)accum - 60; + tmp2 = tmp1 % 1461; + if(tmp2 < 0) { + tmp2 += 1461; + } + tmp1 = (tmp1 - tmp2) / 1461; + time.year = tmp1 * 4; + tmp1 = tmp2 / 365; + if(tmp1 > 3) { + tmp1 = 3; + } + time.year += tmp1 + MACTIMOFFS; + tmp2 -= tmp1 * 365; + tmp1 = 12; + while(mlength[--tmp1] > tmp2); + time.day = tmp2 + 1 - mlength[tmp1]; + time.month = tmp1 + 3; + if(tmp1 > 9) { + time.month = tmp1 - 9; + time.year++; + } + return time; +} + diff --git a/util/util.h b/util/util.h new file mode 100755 index 0000000..90112be --- /dev/null +++ b/util/util.h @@ -0,0 +1,23 @@ +typedef struct real_time { + int year; + int month; + int day; + int hours; + int minutes; + int seconds; +} real_time; + +extern unsigned long get4(); +extern unsigned long get4i(); +extern unsigned long get2(); +extern unsigned long get2i(); +extern unsigned char getb(); +extern void copy(); +extern int do_query(); +extern void put4(); +extern void put2(); +extern void do_indent(); +extern real_time set_time(); +extern unsigned long tomactime(); +extern real_time frommactime(); + diff --git a/util/util.o b/util/util.o new file mode 100644 index 0000000..ee28cc4 Binary files /dev/null and b/util/util.o differ