Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  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
  185.