home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / packery / xpk_source / xpkmaster / open.c < prev    next >
C/C++ Source or Header  |  1996-10-28  |  10KB  |  353 lines

  1. #ifndef XPKMASTER_OPEN_C
  2. #define XPKMASTER_OPEN_C
  3.  
  4. /* Routinesheader
  5.  
  6.     Name:        open.c
  7.     Main:        xpkmaster
  8.     Versionstring:    $VER: open.c 1.1 (28.10.96)
  9.     Author:        SDI
  10.     Distribution:    PD
  11.     Description:    Opening and initialisation routines for XPK files
  12.  
  13.  1.0   06.10.96 : first real version
  14.  1.1   28.10.96 : reincluded A4 support
  15. */
  16.  
  17. #include <exec/types.h>
  18. #include <dos/dos.h>
  19. #include <pragma/exec_lib.h>
  20. #include <pragma/dos_lib.h>
  21. #include "xpkmaster.h"
  22. #include "xpk_strings.h"
  23.  
  24. static LONG getinlen(struct XpkBuffer *xbuf);
  25.  
  26. #define ROW_OF_MINUS    0x2d2d2d2d    /* '----' */
  27. #define PP_COOKIE    0x50503230    /* 'PP20' */
  28.  
  29. LONG __asm xpkopen(register __a0 struct XpkBuffer **xbufp,
  30. register __a1 struct TagItem *tags, register __d2 ULONG examine A4PROTO)
  31. {
  32.   struct Library     *XpkSubBase;
  33.   struct XpkBuffer     *xbuf;
  34.   struct XpkStreamHeader *globhdr;
  35.   struct XpkFib         *fib;
  36.   LONG res;
  37.   LONG bytesread;    /* used to be able to reset after a short read */
  38.  
  39. #if defined(DEBUG) && defined(SUPPORT_A4)
  40.   DebugRunTime("xpkopen: A4 = %ld", a4);
  41. #elif defined (DEBUG)
  42.   DebugRunTime("xpkopen");
  43. #endif
  44.  
  45.   *xbufp = 0;
  46.   if(!(xbuf = initxbuf()))
  47.   {
  48.     parseerrortags(tags);
  49.     return XPKERR_NOMEM;
  50.   }
  51.  
  52. #ifdef SUPPORT_A4
  53.   xbuf->xb_regA4 = a4;
  54. #endif
  55.  
  56.   globhdr = &xbuf->xb_Headers.h_Glob;
  57.   fib = &xbuf->xb_Fib;
  58.  
  59.   if(parsebuftags(xbuf, tags, 0))
  60.     goto Abort;
  61.  
  62.   *xbufp = xbuf;
  63.   if(xbuf->xb_Flags & XMF_PACKING)
  64.     return xpkopenwrite(xbufp, tags);
  65.  
  66.   if(!hookread(xbuf, XIO_READ, globhdr, 4))
  67.   {    /* Read first longword only */
  68.     bytesread = xbuf->xb_InLen = xbuf->xb_RMsg.xmm_Size;
  69.     if(xbuf->xb_Result == XPKERR_TRUNCATED)
  70.       goto Uncompressed;
  71.     else
  72.       goto Abort;
  73.   }
  74.   else
  75.     bytesread = 4;
  76.  
  77.   /**************************** Standard XPK file *********************/
  78.   if(globhdr->xsh_Pack == XPK_COOKIE)
  79.   {    /* Standard XPK packed files */
  80.     UWORD exthlen = 0;        /* size of extended header if present */
  81.  
  82.     xbuf->xb_Format = XPKMODE_UPSTD;
  83.  
  84.     /* Read rest of the global header */
  85.     if(!hookread(xbuf, XIO_READ, (STRPTR) globhdr + 4, sizeof(struct XpkStreamHeader) - 4))
  86.       goto Abort;
  87.  
  88.     if(hchecksum((STRPTR) globhdr, sizeof(struct XpkStreamHeader)))
  89.     {
  90.       xbuf->xb_Result = XPKERR_CHECKSUM;
  91.       goto Abort;
  92.     }
  93.  
  94.     if(!examine && globhdr->xsh_Flags & XPKSTREAMF_PASSWORD &&
  95.     !xbuf->xb_Password)
  96.     {
  97.       xbuf->xb_Result = XPKERR_NEEDPASSWD;
  98.       goto Abort;
  99.     }
  100.  
  101.     if(globhdr->xsh_Flags & XPKSTREAMF_LONGHEADERS)
  102.       xbuf->xb_Headers.h_LocSize = sizeof(struct XpkChunkHdrLong);
  103.     else
  104.       xbuf->xb_Headers.h_LocSize = sizeof(struct XpkChunkHdrWord);
  105.  
  106.     if(globhdr->xsh_Flags & XPKSTREAMF_EXTHEADER)
  107.     {
  108.       if(!hookread(xbuf, XIO_READ, &exthlen, sizeof(UWORD)))
  109.     goto Abort;
  110.       if(!hookread(xbuf, XIO_READ, NULL, exthlen))
  111.     goto Abort;
  112.       exthlen += sizeof(UWORD);    /* for unwinding while XpkExamine */
  113.     }
  114.  
  115.     if(!hookread(xbuf, XIO_READ, &xbuf->xb_Headers.h_Loc,
  116.     xbuf->xb_Headers.h_LocSize))    /* first lochdr */
  117.       goto Abort;
  118.  
  119.     xbuf->xb_Fib.xf_CCur = sizeof(struct XpkStreamHeader);
  120.     updatefib(xbuf);
  121.  
  122.     if(!(xbuf->xb_SubBase = XpkSubBase = opensub(xbuf, globhdr->xsh_Type)))
  123.       goto Abort;
  124.  
  125.     if(globhdr->xsh_SubVrs > xbuf->xb_SubInfo->xi_LibVersion)
  126.     {
  127.       xbuf->xb_Result = XPKERR_OLDSUBLIB;
  128.       goto Abort;
  129.     }
  130.  
  131.     xbuf->xb_ULen = globhdr->xsh_ULen;
  132.     xbuf->xb_Prog.xp_Activity = xbuf->xb_SubInfo->xi_UnpackMsg ?
  133.       xbuf->xb_SubInfo->xi_UnpackMsg : strings[TXT_UNPACKING_UPPER];
  134.     xbuf->xb_Prog.xp_PackerName = xbuf->xb_SubInfo->xi_Name;
  135.     xbuf->xb_LastMsg = xbuf->xb_SubInfo->xi_UnpackedMsg ?
  136.       xbuf->xb_SubInfo->xi_UnpackedMsg : strings[TXT_UNPACKED];
  137.  
  138.     if(globhdr->xsh_Flags & XPKSTREAMF_PASSWORD)
  139.       xbuf->xb_Fib.xf_Flags |= XPKFLAGS_PASSWORD;
  140.  
  141.     if(examine && !hookread(xbuf, XIO_SEEK, 0,
  142.     -(sizeof(struct XpkStreamHeader) + xbuf->xb_Headers.h_LocSize+exthlen)))
  143.       goto Abort;
  144.  
  145.     goto Exit;
  146.   }
  147.  
  148.   if(xbuf->xb_InLen == -1)
  149.   {
  150.     if((res = getinlen(xbuf)))
  151.     {
  152.       xbuf->xb_Result = res;
  153.       goto Abort;
  154.     }
  155.   }
  156.  
  157. #ifdef USE_POWERPACKER
  158.   /***************************** PowerPacker file ***********************/
  159.   if(globhdr->xsh_Pack == PP_COOKIE)
  160.   {
  161.     struct Library *PPBase;
  162.     LONG outsize;
  163.  
  164.     xbuf->xb_Format = XPKMODE_UPPP;
  165.  
  166.     if(!hookread(xbuf, XIO_SEEK, 0, xbuf->xb_InLen - 8))
  167.       goto Abort;                    /* 4 Bytes before EOF */
  168.     if(!hookread(xbuf, XIO_READ, &outsize, 4))
  169.       goto Abort;
  170.     if(!hookread(xbuf, XIO_SEEK, 0, - (xbuf->xb_InLen - 4 + (examine << 2))))
  171.       goto Abort;
  172.  
  173.     outsize >>= 8;
  174.  
  175.     fib->xf_Type = XPKTYPE_PACKED;
  176.     fib->xf_CLen = xbuf->xb_InLen;
  177.     fib->xf_ULen = outsize;
  178.     fib->xf_NLen = outsize + XPK_MARGIN;
  179.     fib->xf_ID = PP_COOKIE;
  180.     percentages (fib);
  181.  
  182.     if(examine)
  183.       goto Exit;
  184.  
  185.     xbuf->xb_Prog.xp_Activity = strings[TXT_UNPACKING_UPPER];
  186.     xbuf->xb_Prog.xp_PackerName = "PowerPacker";
  187.     xbuf->xb_LastMsg = strings[TXT_UNPACKED];
  188.     xbuf->xb_ULen = outsize;
  189.  
  190.     if(!(PPBase = OpenLibrary ("powerpacker.library", 0)))
  191.     {
  192.       xbuf->xb_Result = XPKERR_MISSINGLIB;
  193.       goto Abort;
  194.     }
  195.     xbuf->xb_SubBase = PPBase;
  196.  
  197.     goto Exit;
  198.   }
  199. #endif /* USE_POWERPACKER */
  200.  
  201. /* Future Code
  202.   if((WORD) globhdr->xsh_Pack == 0x1F9D)
  203.   {    // UNIX compress
  204.   }
  205. */
  206.  
  207.   /**************************** Uncompressed file *************************/
  208. Uncompressed:
  209.   if(examine || xbuf->xb_Flags & XMF_PASSTHRU)        /* Unpacked */
  210.   {
  211.     xbuf->xb_Format = XPKMODE_UPUP;
  212.  
  213.     fib->xf_Type = XPKTYPE_UNPACKED;
  214.     fib->xf_CLen = xbuf->xb_InLen;
  215.     fib->xf_ULen = xbuf->xb_InLen;
  216.     fib->xf_NLen = Min(CHUNKSIZE, xbuf->xb_InLen) + XPK_MARGIN;
  217.     fib->xf_ID = ROW_OF_MINUS;
  218.  
  219.     xbuf->xb_Prog.xp_Activity = strings[TXT_READING];
  220.     xbuf->xb_Prog.xp_PackerName = "MASTER";
  221.     xbuf->xb_LastMsg = strings[TXT_READ];
  222.     xbuf->xb_ULen = xbuf->xb_InLen;
  223.  
  224.     xbuf->xb_Result = XPKERR_OK;    /* if != 0 is was XPKERR_TRUNCATED */
  225.     if(!hookread(xbuf, XIO_SEEK, 0, -bytesread))
  226.       goto Abort;
  227.  
  228.     goto Exit;
  229.   }
  230.  
  231.   xbuf->xb_Result = XPKERR_NOTPACKED;    /* Can't unpack, can't passthru */
  232.  
  233. Abort:
  234.   *xbufp = 0;
  235.   return XpkClose(xbuf);
  236.  
  237. Exit:
  238.   *xbufp = xbuf;
  239.   return XPKERR_OK;
  240. }
  241.  
  242. /****************************** Open for packing **************************/
  243. LONG xpkopenwrite(struct XpkBuffer **xbufp, struct TagItem *tags)
  244. {
  245.   struct XpkBuffer        *xbuf        = *xbufp;
  246.   struct XpkStreamHeader    *globhdr    = &xbuf->xb_Headers.h_Glob;
  247.   struct Library        *XpkSubBase;
  248.   LONG                 res;
  249.  
  250.   xbuf->xb_Format = XPKMODE_PKSTD;
  251.  
  252.   if(getinlen(xbuf))        /* Find InLen */
  253.   {
  254.     xbuf->xb_Result = XPKERR_BADPARAMS;
  255.     goto Abort;
  256.   }
  257.  
  258.   if(!(XpkSubBase = xbuf->xb_SubBase))    /* Do we know the sublib? */
  259.   {
  260.     xbuf->xb_Result = XPKERR_BADPARAMS;
  261.     goto Abort;
  262.   }
  263.  
  264.   xbuf->xb_MinChunk = xbuf->xb_SubInfo->xi_MinPkInChunk;
  265.  
  266.   if(xbuf->xb_Password && !(xbuf->xb_SubInfo->xi_Flags & XPKIF_ENCRYPTION))
  267.   {
  268.     xbuf->xb_Result = XPKERR_NOCRYPT;
  269.     goto Abort;
  270.   }
  271.  
  272.   if(!xbuf->xb_Password && xbuf->xb_SubInfo->xi_Flags & XPKIF_NEEDPASSWD)
  273.   {
  274.     xbuf->xb_Result = XPKERR_NEEDPASSWD;
  275.     goto Abort;
  276.   }
  277.  
  278.   if(!(xbuf->xb_Flags & XMF_LOSSYOK) &&
  279.   xbuf->xb_SubInfo->xi_Flags & XPKIF_LOSSY)
  280.   {
  281.     xbuf->xb_Result = XPKERR_LOSSY;
  282.     goto Abort;
  283.   }
  284.  
  285.   if(xbuf->xb_PackingMode > 100)    /* Is packing mode valid? */
  286.     xbuf->xb_PackingMode = 100;        /* Use max */
  287.  
  288.   if(!hookwrite(xbuf, XIO_TOTSIZE, 0,
  289.   (xbuf->xb_InLen + xbuf->xb_InLen / 32 & ~3) + 2 * XPK_MARGIN))
  290.     goto Abort;
  291.  
  292.   /*********************** Find the chunk size *********************/
  293.   if((xbuf->xb_ChunkSize == 0) &&
  294.   ((xbuf->xb_ChunkSize = xbuf->xb_SubInfo->xi_DefPkInChunk) == 0))
  295.     xbuf->xb_ChunkSize = DEFAULTCHUNKSIZE;
  296.   if(xbuf->xb_ChunkSize < xbuf->xb_SubInfo->xi_MinPkInChunk)
  297.     xbuf->xb_ChunkSize = xbuf->xb_SubInfo->xi_MinPkInChunk;
  298.   if((xbuf->xb_SubInfo->xi_MaxPkInChunk) &&
  299.   (xbuf->xb_ChunkSize > xbuf->xb_SubInfo->xi_MaxPkInChunk))
  300.     xbuf->xb_ChunkSize = xbuf->xb_SubInfo->xi_MaxPkInChunk;
  301.  
  302.   /******************* Prepare global header *********************/
  303.   globhdr->xsh_Pack = 0;        /* Initialize the global header */
  304.   globhdr->xsh_Type = xbuf->xb_SubID;
  305.  
  306.   if(xbuf->xb_ChunkSize > 65000)
  307.     globhdr->xsh_Flags |= XPKSTREAMF_LONGHEADERS;
  308.   if(xbuf->xb_Password)
  309.     globhdr->xsh_Flags |= XPKSTREAMF_PASSWORD;
  310.  
  311.   xbuf->xb_Headers.h_LocSize = globhdr->xsh_Flags & XPKSTREAMF_LONGHEADERS
  312.     ? sizeof (struct XpkChunkHdrLong)
  313.     : sizeof (struct XpkChunkHdrWord);
  314.  
  315.   memset(globhdr->xsh_Initial, 0xff, 16);    /* Read first 16 bytes */
  316.  
  317.   xbuf->xb_Prog.xp_Activity = xbuf->xb_SubInfo->xi_PackMsg ?
  318.   xbuf->xb_SubInfo->xi_PackMsg : strings[TXT_PACKING_UPPER];
  319.   xbuf->xb_Prog.xp_PackerName = xbuf->xb_SubInfo->xi_Name;
  320.   xbuf->xb_LastMsg = xbuf->xb_SubInfo->xi_PackedMsg ?
  321.   xbuf->xb_SubInfo->xi_PackedMsg : strings[TXT_PACKED];
  322.  
  323. Abort:
  324.   xbuf->xb_Fib.xf_NLen = Min(xbuf->xb_InLen - xbuf->xb_Fib.xf_UCur,
  325.   xbuf->xb_ChunkSize);
  326.  
  327.   if((res = xbuf->xb_Result))
  328.     res = XpkClose(xbuf);
  329.  
  330.   return res;
  331. }
  332.  
  333. static LONG getinlen(struct XpkBuffer *xbuf)
  334. {
  335.   if(xbuf->xb_InLen == -1)
  336.   {
  337.     if(xbuf->xb_RHook == &fhinhook)
  338.     {    /* For files, find length from here to end */
  339.       LONG opos;
  340.  
  341.       if((opos = Seek(xbuf->xb_RMsg.xmm_FH, 0, OFFSET_END)) < 0 ||
  342.       (xbuf->xb_InLen=Seek(xbuf->xb_RMsg.xmm_FH, opos,OFFSET_BEGINNING)) <0)
  343.     return XPKERR_IOERRIN;
  344.     }
  345.     else if(xbuf->xb_RHook == &meminhook) /* InLen always required for input from memory */
  346.       return XPKERR_BADPARAMS;
  347.     /* For unpacking from custom hooks, InLen is only needed for PowerPacker */
  348.   }
  349.   return 0;
  350. }
  351.  
  352. #endif /* XPKMASTER_OPEN_C */
  353.