home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / packery / xpk_source / xpack / xpack.c < prev   
C/C++ Source or Header  |  1996-10-19  |  11KB  |  476 lines

  1. #include <exec/alerts.h>
  2. #include <exec/memory.h>
  3. #include <exec/execbase.h>
  4.  
  5. #include <dos/dosextens.h>
  6. #include <dos/dosasl.h>
  7. #include <dos/rdargs.h>
  8.  
  9. #include <xpk/xpk.h>
  10.  
  11. #define _USEOLDEXEC_ 1
  12.  
  13. #include <proto/dos.h>
  14. #include <proto/exec.h>
  15.  
  16. #include <string.h>
  17.  
  18. #define XFH_ID "XFH A"
  19.  
  20. void PrintF(char *,...);
  21. LONG __regargs PackFile(struct DosLibrary *DOSBase,struct Library *XpkBase,
  22.                         char *,struct FileInfoBlock *,char *,char *,LONG,char *,
  23.                         LONG,LONG,LONG,LONG,LONG);
  24. LONG __regargs UnPackFile(struct DosLibrary *DOSBase,struct Library *XpkBase,
  25.                           char *,char *,struct FileInfoBlock *,char *,LONG);
  26. LONG __asm __saveds ChunkFunc(register __a1 struct XpkProgress *);
  27.  
  28. struct Hook ChunkHook = {{0L},ChunkFunc};
  29.  
  30. struct xPackArgs
  31.  {
  32.   char **Files;
  33.   char *Method;
  34.   ULONG *MinSize;
  35.   char *Suffix,*Password;
  36.   LONG All,Force,Program,xScan,Lossy,Quiet;
  37.  };
  38.  
  39. char *VersionString = "$VER: xPack 1.5 ("__DATE__")";
  40. char *Template =
  41.  "FILE/M/A,METHOD/K,MINSIZE/N/K,SUFFIX/K,PASSWORD/K,"
  42.  "ALL/S,FORCE/S,PROGRAM/S,XSCAN/S,LOSSY/S,QUIET/S";
  43.  
  44. LONG __saveds main(void)
  45.  
  46. {
  47.  struct DosLibrary *DOSBase;
  48.  struct Library *XpkBase;
  49.  struct Process *MyProc;
  50.  struct RDArgs *RDArgs;
  51.  char ProgName[32];
  52.  LONG Result;
  53.  struct xPackArgs Args;
  54.  char **Files;
  55.  struct AnchorPath *AnchorPath;
  56.  ULONG MinSize;
  57.  
  58.  if ((MyProc=(struct Process *)FindTask(NULL))->pr_CLI==NULL)
  59.   {
  60.    (void)WaitPort(&MyProc->pr_MsgPort);
  61.    Forbid();
  62.    ReplyMsg (GetMsg(&MyProc->pr_MsgPort));
  63.  
  64.    return 0L;
  65.   }
  66.  
  67.  if ((DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",33L))==NULL)
  68.   {
  69.    Alert (AT_Recovery|AG_OpenLib|AO_DOSLib);
  70.  
  71.    return 20L;
  72.   }
  73.  if (DOSBase->dl_lib.lib_Version<37L)
  74.   {
  75.    (void)Write(Output(),"This program requires OS 2.04 or newer.\n",40L);
  76.  
  77.    CloseLibrary (&DOSBase->dl_lib);
  78.    return 20L;
  79.   }
  80.  
  81.  if (!GetProgramName(ProgName,32L)) (void)strcpy(ProgName,"xPack");
  82.  Result=10L;
  83.  
  84.  if ((XpkBase=OpenLibrary(XPKNAME,2L))==NULL)
  85.   {
  86.    PrintF ("%s: %s V2 or newer required !\n",ProgName,XPKNAME);
  87.  
  88.    goto Close1;
  89.   }
  90.  
  91.  Args.Files=NULL;
  92.  Args.Method=Args.Suffix=Args.Password=NULL;
  93.  Args.MinSize=NULL;
  94.  Args.All=Args.Force=Args.Program=Args.xScan=Args.Lossy=Args.Quiet=FALSE;
  95.  if ((RDArgs=ReadArgs(Template,(LONG *)&Args,NULL))==NULL)
  96.   {
  97.    PrintFault (IoErr(),ProgName);
  98.  
  99.    goto Close2;
  100.   }
  101.  
  102.  if (Args.MinSize) MinSize=*Args.MinSize;
  103.  else MinSize=512L;
  104.  if (Args.Password) Args.Force=TRUE;
  105.  
  106.  if ((AnchorPath=(struct AnchorPath *)AllocVec(sizeof(struct AnchorPath)+256L,
  107.                                                MEMF_PUBLIC|MEMF_CLEAR))==NULL)
  108.   {
  109.    PrintFault (ERROR_NO_FREE_STORE,ProgName);
  110.  
  111.    goto Close3;
  112.   }
  113.  AnchorPath->ap_BreakBits=SIGBREAKF_CTRL_C;
  114.  AnchorPath->ap_Strlen=256;
  115.  
  116.  Files=Args.Files;
  117.  while (*Files)
  118.   {
  119.    LONG RetVal;
  120.  
  121.    for (RetVal=MatchFirst(*Files,AnchorPath); RetVal==0L; RetVal=MatchNext(AnchorPath))
  122.     {
  123.      if (AnchorPath->ap_Info.fib_DirEntryType>0L)
  124.       {
  125.        if (((AnchorPath->ap_Flags&APF_DIDDIR)==0L)&&Args.All)
  126.         AnchorPath->ap_Flags|=APF_DODIR;
  127.        AnchorPath->ap_Flags&=~APF_DIDDIR;
  128.       }
  129.      else
  130.       {
  131.        BPTR DirLock;
  132.        LONG Result;
  133.  
  134.        DirLock=CurrentDir(AnchorPath->ap_Current->an_Lock);
  135.        if (Args.Method==NULL)
  136.         Result=UnPackFile(DOSBase,XpkBase,
  137.                           AnchorPath->ap_Buf,Args.Suffix,&AnchorPath->ap_Info,
  138.                           Args.Password,Args.Quiet);
  139.        else
  140.         Result=PackFile(DOSBase,XpkBase,
  141.                         AnchorPath->ap_Buf,&AnchorPath->ap_Info,Args.Method,
  142.                         Args.Suffix,MinSize,Args.Password,
  143.                         Args.Force,Args.Program,Args.xScan,Args.Lossy,Args.Quiet);
  144.        (void)CurrentDir(DirLock);
  145.  
  146.        if (!Result)
  147.         {
  148.          PrintF ("\n*** Aborting\n");
  149.  
  150.          MatchEnd (AnchorPath);
  151.          goto Close4;
  152.         }
  153.       }
  154.     }
  155.    MatchEnd (AnchorPath);
  156.  
  157.    if (RetVal!=ERROR_NO_MORE_ENTRIES)
  158.     {
  159.      PrintF ("%s: %s - ",ProgName,*Files);
  160.      PrintFault (RetVal,NULL);
  161.      
  162.      goto Close4;
  163.     }
  164.    else Files++;
  165.   }
  166.  Result=0L;
  167.  
  168. Close4: /* I hate "goto"s, but it's the only way to keep it short. */
  169.  FreeVec ((APTR)AnchorPath);
  170. Close3:
  171.  FreeArgs (RDArgs);
  172. Close2:
  173.  CloseLibrary (XpkBase);
  174. Close1:
  175.  CloseLibrary (&DOSBase->dl_lib);
  176.  return Result;
  177. }
  178.  
  179. void PrintF(char *FormatString,...)
  180.  
  181. {
  182.  struct DosLibrary *DOSBase;
  183.  
  184.  if (DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37L))
  185.   {
  186.    (void)VPrintf(FormatString,(LONG *)&FormatString+1L);
  187.    (void)Flush(Output());
  188.  
  189.    CloseLibrary (&DOSBase->dl_lib);
  190.   }
  191. }
  192.  
  193. void __regargs TempName(char *Name)
  194.  
  195. {
  196.  UWORD Index;
  197.  ULONG Addr;
  198.  
  199.  for (Index=0, Addr=(ULONG)FindTask(NULL); Index<8; Index++, Addr>>=4)
  200.   *Name++='A'+(char)(Addr&15);
  201.  (void)strcpy(Name,".zop");
  202. }
  203.  
  204. LONG __asm __saveds ChunkFunc(register __a1 struct XpkProgress *Prog)
  205.  
  206. {
  207.  if (Prog->Type==XPKPROG_START ) PrintF ("\x1B[0 p");
  208.  PrintF ("\r%-9s %-12s (%6ld bytes, %3ld%% done, %2ld%% CF) ",
  209.          Prog->Activity,Prog->FileName,Prog->ULen,Prog->Done,Prog->CF);
  210.  if (Prog->Type==XPKPROG_END) PrintF ("\n\x1B[1 p");
  211.  
  212.  return (LONG)SetSignal(0L,SIGBREAKF_CTRL_C)&SIGBREAKF_CTRL_C;
  213. }
  214.  
  215. char *ULTA(char *Ptr,ULONG LW)
  216.  
  217. {
  218.  UWORD Index;
  219.  
  220.  *Ptr++=' ';
  221.  for (Index=0; Index<8; Index++, LW>>=4) Ptr[7-Index]='A'+(char)(LW&15);
  222.  return &Ptr[8];
  223. }
  224.  
  225. #define TAGIT(i,t,d) XpkTags[i].ti_Tag=t; XpkTags[i].ti_Data=(ULONG)d;
  226. #define ENDIT(i) XpkTags[i].ti_Tag=TAG_DONE;
  227.  
  228. LONG __regargs PackFile(struct DosLibrary *DOSBase,struct Library *XpkBase,
  229.                         char *SourceName,struct FileInfoBlock *FIB,char *Method,
  230.                         char *Suffix,LONG MinSize,char *Password,
  231.                         LONG Force,LONG Program,LONG xScan,LONG Lossy,LONG Quiet)
  232.  
  233. {
  234.  BPTR Handle;
  235.  struct TagItem XpkTags[10];
  236.  struct XpkFib XpkFib;
  237.  char ErrorBuffer[XPKERRMSGSIZE],TargetName[108];
  238.  LONG Error,Size;
  239.  
  240.  if (FIB->fib_Protection&FIBF_DELETE)
  241.   {
  242.    PrintF ("Skipping %s (delete protected)\n",SourceName);
  243.    return TRUE;
  244.   }
  245.  if (FIB->fib_Size<=MinSize)
  246.   {
  247.    PrintF ("Skipping %s (too small)\n",SourceName);
  248.    return TRUE;
  249.   }
  250.  if ((Handle=Open(FIB->fib_FileName,MODE_OLDFILE))==NULL)
  251.   {
  252.    PrintF ("Can't open %s\n",SourceName);
  253.    return TRUE;
  254.   }
  255.  if (!Force)
  256.   {
  257.    TAGIT(0,XPK_GetError,ErrorBuffer);
  258.    TAGIT(1,XPK_InFH,Handle);
  259.    ENDIT(2);
  260.    if (XpkExamine(&XpkFib,XpkTags))
  261.     {
  262.      Close (Handle);
  263.  
  264.      PrintF ("%s\n",ErrorBuffer);
  265.      return TRUE;
  266.     }
  267.    if (XpkFib.Type!=XPKTYPE_UNPACKED)
  268.     {
  269.      Close (Handle);
  270.  
  271.      PrintF ("Skipping %s (already crunched)\n",SourceName);
  272.      return TRUE;
  273.     }
  274.   }
  275.  if (Program)
  276.   {
  277.    LONG Buffer[5];
  278.  
  279.    if (Read(Handle,Buffer,20L)!=20L)
  280.     {
  281.      Close (Handle);
  282.  
  283.      PrintF ("Skipping %s (to small for executable)\n",SourceName);
  284.      return TRUE;
  285.     }
  286.    if (Buffer[0]!=0x3F3L)
  287.     {
  288.      Close (Handle);
  289.  
  290.      PrintF ("Skipping %s (not executable)\n",SourceName);
  291.      return TRUE;
  292.     }
  293.    if ((Buffer[3]!=0L)||((Buffer[4]+1L)!=Buffer[2]))
  294.     {
  295.      Close (Handle);
  296.  
  297.      PrintF ("Skipping %s (overlayed)\n",SourceName);
  298.      return TRUE;
  299.     }
  300.    (void)Seek(Handle,0L,OFFSET_BEGINNING);
  301.   }
  302.  
  303.  if (Suffix)
  304.   {
  305.    ULONG Length;
  306.  
  307.    Length=strlen(strcpy(TargetName,FIB->fib_FileName));
  308.    (void)strcpy(&TargetName[Length],Suffix);
  309.   }
  310.  else TempName (TargetName);
  311.  Size=0L;
  312.  
  313.  TAGIT(0,XPK_GetError,ErrorBuffer);
  314.  TAGIT(1,XPK_Password,Password);
  315.  TAGIT(2,XPK_FindMethod,Method);
  316.  TAGIT(3,XPK_ChunkHook,&ChunkHook);
  317.  if (Quiet) XpkTags[3].ti_Tag=TAG_IGNORE;
  318.  TAGIT(4,XPK_FileName,FIB->fib_FileName);
  319.  TAGIT(5,XPK_InFH,Handle);
  320.  TAGIT(6,XPK_OutName,TargetName);
  321.  TAGIT(7,XPK_GetOutLen,&Size);
  322.  TAGIT(8,XPK_LossyOK,Lossy);
  323.  if (!Lossy) XpkTags[8].ti_Tag=TAG_IGNORE;
  324.  ENDIT(9);
  325.  
  326.  if (Error=XpkPack(XpkTags))
  327.   {
  328.    Close (Handle);
  329.  
  330.    PrintF ("%s\n",ErrorBuffer);
  331.    return (Error!=XPKERR_ABORTED);
  332.   }
  333.  Close (Handle);
  334.  
  335.  if ((Size>FIB->fib_Size)&&(!Force))
  336.   {
  337.    (void)DeleteFile(TargetName);
  338.  
  339.    PrintF ("Skipping %s (unable to reduce size)\n",SourceName);
  340.    return TRUE;
  341.   }
  342.  
  343.  if (FIB->fib_Comment[0]=='\0')
  344.   if (xScan)
  345.    {
  346.     char *Ptr;
  347.  
  348.     Ptr=strcpy(FIB->fib_Comment,XFH_ID)+strlen(XFH_ID);
  349.     Ptr=ULTA(Ptr,FIB->fib_Date.ds_Days);
  350.     Ptr=ULTA(Ptr,FIB->fib_Date.ds_Minute);
  351.     Ptr=ULTA(Ptr,FIB->fib_Date.ds_Tick);
  352.     Ptr=ULTA(Ptr,Size);
  353.     *ULTA(Ptr,FIB->fib_Size)='\0';
  354.    }
  355.  
  356.  if (FIB->fib_Comment[0]) (void)SetComment(TargetName,FIB->fib_Comment);
  357.  
  358.  if (FIB->fib_Protection) (void)SetProtection(TargetName,FIB->fib_Protection);
  359.  (void)SetFileDate(TargetName,&FIB->fib_Date);
  360.  
  361.  if (Suffix) return TRUE;
  362.  
  363.  if (!DeleteFile(FIB->fib_FileName))
  364.   {
  365.    (void)DeleteFile(TargetName);
  366.  
  367.    PrintF ("Unable to delete %s\n",SourceName);
  368.    return TRUE;
  369.   }
  370.  if (!Rename(TargetName,FIB->fib_FileName))
  371.   {
  372.    PrintF ("Unable to rename %s to %s\n",TargetName,FIB->fib_FileName);
  373.    return FALSE;
  374.   }
  375.  
  376.  return TRUE;
  377. }
  378.  
  379. LONG __regargs UnPackFile(struct DosLibrary *DOSBase,struct Library *XpkBase,
  380.                           char *SourceName,char *Suffix,
  381.                           struct FileInfoBlock *FIB,char *Password,LONG Quiet)
  382.  
  383. {
  384.  BPTR Handle;
  385.  struct TagItem XpkTags[7];
  386.  struct XpkFib XpkFib;
  387.  char ErrorBuffer[XPKERRMSGSIZE],TargetName[108];
  388.  LONG SameFile,Error;
  389.  
  390.  if (FIB->fib_Protection&FIBF_DELETE)
  391.   {
  392.    PrintF ("Skipping %s (delete protected)\n",SourceName);
  393.    return TRUE;
  394.   }
  395.  if ((Handle=Open(FIB->fib_FileName,MODE_OLDFILE))==NULL)
  396.   {
  397.    PrintF ("Can't open %s\n",SourceName);
  398.    return TRUE;
  399.   }
  400.  
  401.  TAGIT(0,XPK_GetError,ErrorBuffer);
  402.  TAGIT(1,XPK_InFH,Handle);
  403.  ENDIT(2);
  404.  
  405.  if (XpkExamine(&XpkFib,XpkTags))
  406.   {
  407.    Close (Handle);
  408.  
  409.    PrintF ("%s\n",ErrorBuffer);
  410.    return TRUE;
  411.   }
  412.  if (XpkFib.Type!=XPKTYPE_PACKED)
  413.   {
  414.    Close (Handle);
  415.  
  416.    PrintF ("Skipping %s (not crunched)\n",SourceName);
  417.    return TRUE;
  418.   }
  419.  
  420.  TempName (TargetName);
  421.  SameFile=TRUE;
  422.  if (Suffix)
  423.   {
  424.    LONG Len1,Len2;
  425.  
  426.    Len1=strlen(FIB->fib_FileName);
  427.    Len2=strlen(Suffix);
  428.    if (Len1>Len2)
  429.     if (stricmp(&FIB->fib_FileName[Len1-Len2],Suffix)==0)
  430.      {
  431.       strcpy(TargetName,FIB->fib_FileName)[Len1-Len2]='\0';
  432.       SameFile=FALSE;
  433.      }
  434.   }
  435.  
  436.  TAGIT(0,XPK_GetError,ErrorBuffer);
  437.  TAGIT(1,XPK_Password,Password);
  438.  TAGIT(2,XPK_ChunkHook,&ChunkHook);
  439.  if (Quiet) XpkTags[2].ti_Tag=TAG_IGNORE;
  440.  TAGIT(3,XPK_FileName,FIB->fib_FileName);
  441.  TAGIT(4,XPK_InFH,Handle);
  442.  TAGIT(5,XPK_OutName,TargetName);
  443.  ENDIT(6);
  444.  
  445.  if (Error=XpkUnpack(XpkTags))   {
  446.    Close (Handle);
  447.  
  448.    PrintF ("%s\n",ErrorBuffer);
  449.    return (Error!=XPKERR_ABORTED);
  450.   }
  451.  Close (Handle);
  452.  
  453.  if (FIB->fib_Comment[0])
  454.   if (strncmp(FIB->fib_Comment,XFH_ID,strlen(XFH_ID))!=0)
  455.    (void)SetComment(TargetName,FIB->fib_Comment);
  456.  if (FIB->fib_Protection) (void)SetProtection(TargetName,FIB->fib_Protection);
  457.  (void)SetFileDate(TargetName,&FIB->fib_Date);
  458.  
  459.  if (!SameFile) return TRUE;
  460.  
  461.  if (!DeleteFile(FIB->fib_FileName))
  462.   {
  463.    (void)DeleteFile(TargetName);
  464.  
  465.    PrintF ("Unable to delete %s\n",SourceName);
  466.    return TRUE;
  467.   }
  468.  if (!Rename(TargetName,FIB->fib_FileName))
  469.   {
  470.    PrintF ("Unable to rename %s to %s\n",TargetName,FIB->fib_FileName);
  471.    return FALSE;
  472.   }
  473.  
  474.  return TRUE;
  475. }
  476.