makesfx.c
上传用户:andy_li
上传日期:2007-01-06
资源大小:1019k
文件大小:6k
源码类别:

压缩解压

开发平台:

MultiPlatform

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