home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / unzip531.zip / amiga / makesfx.c < prev    next >
C/C++ Source or Header  |  1996-07-25  |  6KB  |  172 lines

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