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