1 | /*
|
---|
2 | Copyright (c) 1990-2000 Info-ZIP. All rights reserved.
|
---|
3 |
|
---|
4 | See the accompanying file LICENSE, version 2000-Apr-09 or later
|
---|
5 | (the contents of which are also included in unzip.h) for terms of use.
|
---|
6 | If, for some reason, all these files are missing, the Info-ZIP license
|
---|
7 | also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
|
---|
8 | */
|
---|
9 | /* MakeSFX: join UnZipSFX and a .zip archive into a single self-extracting */
|
---|
10 | /* Amiga program. On most systems simple concatenation does the job but for */
|
---|
11 | /* the Amiga a special tool is needed. By Paul Kienitz, no rights reserved. */
|
---|
12 | /* This program is written portably, so if anyone really wants to they can */
|
---|
13 | /* produce Amiga self-extracting programs on a non-Amiga. We are careful */
|
---|
14 | /* not to mix Motorola-format longwords read from files with native long */
|
---|
15 | /* integers. Not necessarily limited to use with only the Zip format -- */
|
---|
16 | /* just combine any archive with any self-extractor program that is capable */
|
---|
17 | /* of reading a HUNK_DEBUG section at the end as an archive. */
|
---|
18 |
|
---|
19 | #include <stat.h>
|
---|
20 | #include <string.h>
|
---|
21 | #include <stdio.h>
|
---|
22 | #include <stdlib.h>
|
---|
23 | #ifdef __SASC
|
---|
24 | # include <proto/dos.h>
|
---|
25 | # ifdef DEBUG
|
---|
26 | # include <sprof.h>
|
---|
27 | # endif
|
---|
28 | #endif /* __SASC */
|
---|
29 | #ifdef AZTEC_C
|
---|
30 | # include <dos/dos.h>
|
---|
31 | # include <clib/dos_protos.h>
|
---|
32 | #endif /* AZTEC_C */
|
---|
33 |
|
---|
34 | typedef unsigned long ulg;
|
---|
35 | typedef unsigned char uch;
|
---|
36 | typedef unsigned short bool;
|
---|
37 | #define false 0
|
---|
38 | #define true 1
|
---|
39 |
|
---|
40 | /* the following are extracted from Commodore include file dos/doshunks.h: */
|
---|
41 | #define HUNK_NAME 1000L
|
---|
42 | #define HUNK_CODE 1001L
|
---|
43 | #define HUNK_DATA 1002L
|
---|
44 | #define HUNK_BSS 1003L
|
---|
45 | #define HUNK_RELOC32 1004L
|
---|
46 | #define HUNK_SYMBOL 1008L
|
---|
47 | #define HUNK_DEBUG 1009L
|
---|
48 | #define HUNK_END 1010L
|
---|
49 | #define HUNK_HEADER 1011L
|
---|
50 | #define HUNK_OVERLAY 1013L
|
---|
51 | #define HUNK_BREAK 1014L
|
---|
52 |
|
---|
53 | /* Convert a big-endian (Motorola) sequence of four bytes to a longword: */
|
---|
54 | #define CHARS2LONG(b) (((ulg)(b)[0] << 24) | ((ulg)(b)[1] << 16) | \
|
---|
55 | ((ulg)(b)[2] << 8) | ((ulg)(b)[3]))
|
---|
56 | /* b must be (uch *) in each of these. Now the reverse: */
|
---|
57 | #define LONG2CHARS(b,l) ((b)[0] = (uch)((l) >> 24), (b)[1] = (uch)((l) >> 16),\
|
---|
58 | (b)[2] = (uch)((l) >> 8), (b)[3] = (uch)(l))
|
---|
59 |
|
---|
60 | #define COPYBUFFER 16384
|
---|
61 |
|
---|
62 | ulg totalwritten = 0;
|
---|
63 |
|
---|
64 |
|
---|
65 | bool CopyData(FILE *out, FILE *inn, ulg archivesize,
|
---|
66 | char *outname, char *inname)
|
---|
67 | {
|
---|
68 | static uch buf[COPYBUFFER];
|
---|
69 | ulg written;
|
---|
70 | size_t chunk;
|
---|
71 |
|
---|
72 | if (archivesize) {
|
---|
73 | LONG2CHARS(buf, HUNK_DEBUG);
|
---|
74 | written = (archivesize + 3) / 4;
|
---|
75 | LONG2CHARS(buf + 4, written);
|
---|
76 | if (fwrite(buf, 1, 8, out) < 8) {
|
---|
77 | printf("Error writing in-between data to %s\n", outname);
|
---|
78 | return false;
|
---|
79 | }
|
---|
80 | totalwritten += 8;
|
---|
81 | }
|
---|
82 | written = 0;
|
---|
83 | do {
|
---|
84 | chunk = fread(buf, 1, COPYBUFFER, inn);
|
---|
85 | if (ferror(inn)) {
|
---|
86 | printf("Error reading data from %s\n", inname);
|
---|
87 | return false;
|
---|
88 | }
|
---|
89 | if (!archivesize && !written) { /* true only for first block read */
|
---|
90 | if (CHARS2LONG(buf) != HUNK_HEADER) {
|
---|
91 | printf("%s is not an Amiga executable.\n", inname);
|
---|
92 | return false;
|
---|
93 | }
|
---|
94 | }
|
---|
95 | if (fwrite(buf, 1, chunk, out) < chunk) {
|
---|
96 | printf("Error writing %s to %s\n", archivesize ? "archive data" :
|
---|
97 | "self-extractor code", outname);
|
---|
98 | return false;
|
---|
99 | }
|
---|
100 | written += chunk;
|
---|
101 | totalwritten += chunk;
|
---|
102 | } while (!feof(inn));
|
---|
103 | if (archivesize) {
|
---|
104 | if (written != archivesize) {
|
---|
105 | printf("Wrong number of bytes copied from archive %s\n", outname);
|
---|
106 | return false;
|
---|
107 | }
|
---|
108 | LONG2CHARS(buf, 0);
|
---|
109 | chunk = 3 - (written + 3) % 4;
|
---|
110 | LONG2CHARS(buf + chunk, HUNK_END);
|
---|
111 | chunk += 4;
|
---|
112 | if (fwrite(buf, 1, chunk, out) < chunk) {
|
---|
113 | printf("Error writing end-marker data to %s\n", outname);
|
---|
114 | return false;
|
---|
115 | }
|
---|
116 | totalwritten += chunk;
|
---|
117 | }
|
---|
118 | return true;
|
---|
119 | }
|
---|
120 |
|
---|
121 |
|
---|
122 | void main(int argc, char **argv)
|
---|
123 | {
|
---|
124 | FILE *out, *arch, *tool;
|
---|
125 | char *toolname = argv[3];
|
---|
126 | struct stat ss;
|
---|
127 | int ret;
|
---|
128 | ulg archivesize;
|
---|
129 |
|
---|
130 | if (argc < 3 || argc > 4) {
|
---|
131 | printf("Usage: %s <result-file> <zip-archive> [<self-extractor-"
|
---|
132 | "program>]\nThe third arg defaults to \"UnZipSFX\" in the"
|
---|
133 | " current dir or C:.\n", argv[0]);
|
---|
134 | exit(20);
|
---|
135 | }
|
---|
136 | if (!(arch = fopen(argv[2], "rb"))) {
|
---|
137 | printf("Could not find archive file %s\n", argv[2]);
|
---|
138 | exit(10);
|
---|
139 | }
|
---|
140 | if (stat(argv[2], &ss) || !(archivesize = ss.st_size)) {
|
---|
141 | fclose(arch);
|
---|
142 | printf("Could not check size of archive %s, or file is empty.\n",
|
---|
143 | argv[2]);
|
---|
144 | exit(10);
|
---|
145 | }
|
---|
146 | if (argc < 4)
|
---|
147 | toolname = "UnZipSFX";
|
---|
148 | if (!(tool = fopen(toolname, "rb"))) {
|
---|
149 | BPTR lk = Lock("C:", ACCESS_READ);
|
---|
150 | BPTR ocd = lk ? CurrentDir(lk) : 0;
|
---|
151 | if (!(tool = fopen(toolname, "rb"))) {
|
---|
152 | fclose(arch);
|
---|
153 | printf("Could not find self-extractor program %s\n", toolname);
|
---|
154 | if (lk)
|
---|
155 | UnLock(CurrentDir(ocd));
|
---|
156 | exit(10);
|
---|
157 | }
|
---|
158 | if (lk)
|
---|
159 | UnLock(CurrentDir(ocd));
|
---|
160 | }
|
---|
161 | if (!(out = fopen(argv[1], "wb"))) {
|
---|
162 | fclose(arch);
|
---|
163 | fclose(tool);
|
---|
164 | printf("Could not create output file %s\n", argv[1]);
|
---|
165 | exit(10);
|
---|
166 | }
|
---|
167 | ret = CopyData(out, tool, 0, argv[1], toolname)
|
---|
168 | && CopyData(out, arch, archivesize, argv[1], argv[2]) ? 0 : 10;
|
---|
169 | fclose(out);
|
---|
170 | fclose(arch);
|
---|
171 | fclose(tool);
|
---|
172 | if (ret) {
|
---|
173 | printf("Deleting %s\n", argv[1]);
|
---|
174 | remove(argv[1]);
|
---|
175 | } else
|
---|
176 | printf("%s successfully written, size %lu bytes.\n",
|
---|
177 | argv[1], totalwritten);
|
---|
178 | exit(ret);
|
---|
179 | }
|
---|
180 |
|
---|
181 |
|
---|
182 | #if (defined(AZTEC_C) && defined(MCH_AMIGA))
|
---|
183 | void _wb_parse(void) { } /* avoid unneeded infrastructure */
|
---|
184 | #endif
|
---|