home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / vp21beta.zip / AEXMPSRC.RAR / UNRAR / UNRAR.C < prev    next >
C/C++ Source or Header  |  2000-08-15  |  21KB  |  850 lines

  1. /******    *****   ******
  2.  **   **  **   **  **   **      unRAR utility version 1.01
  3.  ******   *******  ******       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4.  **   **  **   **  **   **         FREE portable version
  5.  **   **  **   **  **   **         ~~~~~~~~~~~~~~~~~~~~~
  6.  
  7.          Main code
  8.  
  9.    YOU CAN CHANGE FOLLOWING CODE IN ORDER TO ACHIEVE
  10.    COMPATIBILITY WITH YOUR OPERATING MEDIA.
  11.  
  12.    PLEASE SEND ALL NOTES, PATCHES TO andrey@vybor.chel.su
  13.    OR TO Andrey Spasibozhko, 2:5010/23@fidonet.
  14.    VOICE PHONE: +7-3512-130-231
  15. */
  16.  
  17. #include "unrar.h"          /* definitions */
  18. #include "unpack.c"         /* unpacking procedures */
  19.  
  20. void   SplitCommandLine();  /* parses command string */
  21. int    CmpName();           /* checks name for mask */
  22. char*  PointToName();       /* returns pathname */
  23. void   NextVolumeName();    /* gets next volume name */
  24. void   SplitName();         /* splits pathname */
  25. void   ExecuteCommand();    /* executes extr. command */
  26. void   ListArchive();       /* lists archive contents */
  27. int    ExtrFile();          /* extracts single file */
  28. void   Help();              /* prints usage help */
  29. void   ShutDown();          /* stops working */
  30. void   ErrExit();           /* exits with error code */
  31. void   CreatePath();        /* creates path */
  32. int    tread();             /* reads with checking */
  33. void   tclose();            /* closes with checking */
  34. void   MergeArc();          /* to next volume */
  35. void   UnstoreFile();       /* unpacks non-compressed file */
  36. int    IsArchive();         /* checks for RAR archive signature */
  37. void   CheckArc();          /* similar but with exit */
  38. int    strnicomp();         /* compares strings */
  39. char*  strtolwr();          /* convert string to lowercase
  40. int    ToPercent();         /* calculates percentage */
  41. int    ReadBlock();         /* reads archive block */
  42. int    IsProcessFile();     /* should file be processed */
  43. int    UnpRead();           /* reading while unpacking */
  44. int    UnpWrite();          /* writing while unpacking */
  45. void   InitCRC();           /* initializes CRC table */
  46. UDWORD CRC();               /* calculates CRC */
  47.  
  48. struct MarkHeader MarkHead;
  49. struct ArchiveHeader Mhd;
  50. struct FileHeader Lhd;
  51.  
  52. UDWORD CRC32_Table[256],UnpFileCRC;
  53. HPBYTE TmpMemory;
  54.  
  55. int ArgCount=0;
  56. char ArgNames[16][80],MainCommand;
  57. char CurExtrFile[80]={0},ArcName[80],ArcFileName[80],ExtrPath[80];
  58. int SolidType,UnpVolume,TestMode,ExitCode=0;
  59. FILE *ArcFPtr=NULL,*FileFPtr=NULL,*RdUnpFPtr,*WrUnpFPtr;
  60. long NextBlockPos,UnpPackedSize;
  61.  
  62.  
  63. main(Argc,Argv)
  64. int Argc;
  65. char *Argv[];
  66. {
  67.   printf("\n UNRAR 1.01 freeware portable version      (C) 1994-95 Eugene Roshal\n");
  68.   if ((TmpMemory=(HPBYTE)MEMALLOC(UNP_MEMORY))==NULL)
  69.     ErrExit(EMEMORY,MEMORY_ERROR);
  70.   MakeTbl();
  71.   SplitCommandLine(Argc,Argv);
  72.   ExecuteCommand();
  73.   ShutDown(SD_MEMORY);
  74.   exit(ExitCode);
  75. }
  76.  
  77.  
  78. int CmpName(Mask,Name)
  79. char *Mask;
  80. char *Name;
  81. {
  82.   while (1)
  83.   {
  84.     if (*Mask=='*')
  85.     {
  86.       while (*Mask!='.' && *Mask!=0)
  87.         Mask++;
  88.       while (*Name!='.' && *Name!=0)
  89.         Name++;
  90.     }
  91.     if (*Mask==0)
  92.       return(*Name==0);
  93.     if (*Name==0 && *Mask=='.')
  94.     {
  95.       Mask++;
  96.       continue;
  97.     }
  98.     if (toupper(*Mask)==toupper(*Name) || *Mask=='?' && *Name!=0)
  99.     {
  100.       Mask++;
  101.       Name++;
  102.     }
  103.     else
  104.       return(0);
  105.   }
  106. }
  107.  
  108.  
  109. void ErrExit(ErrCode,Code)
  110. int ErrCode;
  111. int Code;
  112. {
  113.   char ErrMsg[80];
  114.   switch(ErrCode)
  115.   {
  116.     case EEMPTY:
  117.       strcpy(ErrMsg,"");
  118.       break;
  119.     case EWRITE:
  120.       strcpy(ErrMsg,"Write error. Disk full ?");
  121.       break;
  122.     case EREAD:
  123.       strcpy(ErrMsg,"Read error");
  124.       break;
  125.     case EOPEN:
  126.       strcpy(ErrMsg,"File open error");
  127.       break;
  128.     case ECLOSE:
  129.       strcpy(ErrMsg,"File close error");
  130.       break;
  131.     case EMEMORY:
  132.       strcpy(ErrMsg,"Not enough memory");
  133.       break;
  134.     case EARCH:
  135.       strcpy(ErrMsg,"Broken archive");
  136.       break;
  137.   }
  138.   if (ErrCode!=EEMPTY)
  139.     printf("\n Program aborted\n %s",ErrMsg);
  140.   ShutDown(SD_FILES | SD_MEMORY);
  141.   exit(Code);
  142. }
  143.  
  144.  
  145. void CreatePath(fpath)
  146. char *fpath;
  147. {
  148.   char *ChPtr;
  149.   ChPtr=fpath;
  150.   while(*ChPtr!=0 && (ChPtr=strchr(ChPtr,PATHDIV))!=NULL)
  151.   {
  152.     *ChPtr=0;
  153.     if (MAKEDIR(fpath)==0)
  154.       printf("\n Creating    %-55s",fpath);
  155.     *ChPtr=PATHDIV;
  156.     ChPtr++;
  157.   }
  158. }
  159.  
  160.  
  161. void NextVolumeName()
  162. {
  163.   char *ChPtr;
  164.   ChPtr=strrchr(ArcName,'.');
  165.   if (!isdigit(*(ChPtr+2)) || !isdigit(*(ChPtr+3)))
  166.     strcpy(ChPtr+2,"00");
  167.   else
  168.   {
  169.     ChPtr+=3;
  170.     while ((++(*ChPtr))=='9'+1)
  171.     {
  172.       if (*(ChPtr-1)=='.')
  173.       {
  174.         *ChPtr='A';
  175.         break;
  176.       }
  177.       else
  178.       {
  179.         *ChPtr='0';
  180.         ChPtr--;
  181.       }
  182.     }
  183.   }
  184. }
  185.  
  186.  
  187. void MergeArc(ShowFileName)
  188. int ShowFileName;
  189. {
  190.   int Ch;
  191.   tclose(ArcFPtr);
  192.   NextVolumeName();
  193.   while ((ArcFPtr=fopen(ArcName,FOPENREADMODE))==NULL)
  194.   {
  195.     printf("\n Disk with %s required. Continue ? ",ArcName);
  196.     Ch=getchar();
  197.     if (toupper(Ch)=='N')
  198.       ErrExit(EEMPTY,USER_BREAK);
  199.   }
  200.   if (MainCommand=='T')
  201.     printf("\n\n Testing archive %s",ArcName);
  202.   else
  203.     if (MainCommand!='P')
  204.       printf("\n\n Extracting from %s",ArcName);
  205.   CheckArc();
  206.   ReadBlock(FILE_HEAD);
  207.   if (ShowFileName)
  208.     printf("\n     ...     %-55s",ArcFileName);
  209.   UnpVolume=(Lhd.Flags & LHD_SPLIT_AFTER);
  210.   fseek(ArcFPtr,NextBlockPos-Lhd.PackSize,SEEK_SET);
  211.   UnpPackedSize=Lhd.PackSize;
  212.   RdUnpFPtr=ArcFPtr;
  213. }
  214.  
  215.  
  216. void UnstoreFile()
  217. {
  218.   int Code;
  219.   while ( 1 )
  220.   {
  221.     if ((Code=UnpRead((UBYTE *)TmpMemory,0x7f00))==-1)
  222.       ErrExit(EWRITE,WRITE_ERROR);
  223.     if (Code==0)
  224.       break;
  225.     if (UnpWrite((UBYTE *)TmpMemory,(UWORD)Code)==-1)
  226.       ErrExit(EWRITE,WRITE_ERROR);
  227.   }
  228. }
  229.  
  230.  
  231. int IsArchive()
  232. {
  233.   UBYTE Mark[7],Header[13];
  234.   SolidType=0;
  235.   if (tread(ArcFPtr,Mark,7)!=7)
  236.     return(0);
  237.   if (Mark[0]!=0x52 || Mark[1]!=0x61 || Mark[2]!=0x72 || Mark[3]!=0x21 ||
  238.       Mark[4]!=0x1a || Mark[5]!=0x07 || Mark[6]!=0x00)
  239.     return(0);
  240.   if (tread(ArcFPtr,Header,13) != 13)
  241.     return(0);
  242.   Mhd.HeadCRC  = Header[0]+(UWORD)Header[1]*0x100;
  243.   Mhd.HeadType = Header[2];
  244.   Mhd.Flags    = Header[3]+(UWORD)Header[4]*0x100;
  245.   Mhd.HeadSize = Header[5]+(UWORD)Header[6]*0x100;
  246.   if (!(Mhd.HeadCRC==(UWORD)~CRC(0xFFFFFFFFL,&Header[2],11)))
  247.     printf("\n Archive header broken");
  248.   SolidType=(Mhd.Flags & MHD_SOLID);
  249.   fseek(ArcFPtr,Mhd.HeadSize-13,SEEK_CUR);
  250.   return(1);
  251. }
  252.  
  253.  
  254. void CheckArc()
  255. {
  256.   if (!IsArchive())
  257.   {
  258.     printf("\nBad archive %s",ArcName);
  259.     ErrExit(EEMPTY,FATAL_ERROR);
  260.   }
  261. }
  262.  
  263.  
  264. int tread(FPtr,buf,len)
  265. FILE *FPtr;
  266. void *buf;
  267. unsigned len;
  268. {
  269.   int Code;
  270.   Code=fread(buf,1,len,FPtr);
  271.   if (Code==-1)
  272.     ErrExit(EREAD,FATAL_ERROR);
  273.   return(Code);
  274. }
  275.  
  276.  
  277. void tclose(FPtr)
  278. FILE *FPtr;
  279. {
  280.   if (fclose(FPtr)==EOF)
  281.     ErrExit(ECLOSE,FATAL_ERROR);
  282. }
  283.  
  284.  
  285. char* PointToName(Path)
  286. char *Path;
  287. {
  288.   char *ChPtr;
  289.   if ((ChPtr=strrchr(Path,PATHDIV))!=NULL)
  290.     return(ChPtr+1);
  291.   else
  292.     if ((ChPtr=strrchr(Path,':'))!=NULL)
  293.       return(ChPtr+1);
  294.     else
  295.       return(Path);
  296. }
  297.  
  298.  
  299. int strnicomp(Str1,Str2,MaxLen)
  300. char *Str1;
  301. char *Str2;
  302. int MaxLen;
  303. {
  304.   if (MaxLen==0)
  305.     return(0);
  306.   while (MaxLen-- > 0)
  307.   {
  308.     if (toupper(*Str1)!=toupper(*Str2))
  309.       return(1);
  310.     if (*Str1==0)
  311.       return(0);
  312.     Str1++;
  313.     Str2++;
  314.   }
  315.   return(0);
  316. }
  317.  
  318.  
  319. char* strtolwr(Str)
  320. char *Str;
  321. {
  322.   char *ChPtr;
  323.   for (ChPtr=Str;*ChPtr!=0;ChPtr++)
  324.     *ChPtr=tolower(*ChPtr);
  325.   return(Str);
  326. }
  327.  
  328.  
  329. void SplitName(Path,Dir,Name)
  330. char *Path;
  331. char *Dir;
  332. char *Name;
  333. {
  334.   char *ChPtr,*ChPtr1;
  335.   if ((ChPtr=strrchr(Path,':'))!=NULL)
  336.     ChPtr++;
  337.   else
  338.     ChPtr=Path;
  339.   if ((ChPtr1=strrchr(ChPtr,PATHDIV))!=NULL)
  340.   {
  341.     *ChPtr1=0;
  342.     strcpy(Dir,ChPtr);
  343.     *ChPtr1=PATHDIV;
  344.     ChPtr=ChPtr1+1;
  345.   }
  346.   else
  347.     *Dir=0;
  348.   strcpy(Name,ChPtr);
  349. }
  350.  
  351.  
  352. int ToPercent(N1,N2)
  353. long N1;
  354. long N2;
  355. {
  356.   if (N1 > 10000)
  357.   {
  358.     N1/=100;
  359.     N2/=100;
  360.   }
  361.   if (N2==0)
  362.     return(0);
  363.   if (N2<N1)
  364.     return(100);
  365.   return((int)(N1*100/N2));
  366. }
  367.  
  368.  
  369. void SplitCommandLine(Argc,Argv)
  370. int Argc;
  371. char *Argv[];
  372. {
  373.   int I,Len;
  374.  
  375.   ArgCount = MainCommand = *ArcName = *ExtrPath = 0;
  376.  
  377.   if (Argc==2)
  378.   {
  379.     MainCommand='X';
  380.     strcpy(ArcName,Argv[1]);
  381.   }
  382.   else
  383.     for (I=1;I<Argc;I++)
  384.     {
  385.       if (MainCommand==0)
  386.         MainCommand=toupper(Argv[I][0]);
  387.       else
  388.       {
  389.         if (*ArcName==0)
  390.           strncpy(ArcName,Argv[I],80);
  391.         else
  392.         {
  393.           Len=strlen(Argv[I]);
  394.           if (Len>0 && (Argv[I][Len-1]==':' || (Argv[I][Len-1]=='\\' || Argv[I][Len-1]=='/')))
  395.           {
  396.             strcpy(ExtrPath,Argv[I]);
  397.             ExtrPath[Len-1]=PATHDIV;
  398.           }
  399.           else
  400.             strncpy(ArgNames[(ArgCount++) & 0x0f],Argv[I],80);
  401.         }
  402.       }
  403.     }
  404.  
  405.   if (ArgCount==0 && *ArcName!=0)
  406.     strcpy(ArgNames[(ArgCount++) & 0x0f],"*.*");
  407.   if (strrchr(PointToName(ArcName),'.')==NULL)
  408.     strcat(ArcName,isupper(*ArcName) ? ".RAR":".rar");
  409.   ArgCount &= 0xF;
  410. }
  411.  
  412.  
  413. void ExecuteCommand()
  414. {
  415.   switch(MainCommand)
  416.   {
  417.     case 'E':
  418.     case 'X':
  419.     case 'T':
  420.       ExtrFile();
  421.       break;
  422.     case 'V':
  423.     case 'L':
  424.       ListArchive();
  425.       break;
  426.     case 0:
  427.       Help();
  428.       exit(0);
  429.     default:
  430.       Help();
  431.       exit(USER_ERROR);
  432.   }
  433. }
  434.  
  435. void ShutDown(Mode)
  436. int Mode;
  437. {
  438.   if (Mode & SD_FILES)
  439.   {
  440.     if (ArcFPtr!=NULL)
  441.       fclose(ArcFPtr);
  442.     if (FileFPtr!=NULL)
  443.       fclose(FileFPtr);
  444.   }
  445.   if (Mode & SD_MEMORY)
  446.   {
  447.     if (TmpMemory!=NULL)
  448.       MEMFREE(TmpMemory);
  449.     printf("\n");
  450.   }
  451. }
  452.  
  453.  
  454. void Help()
  455. {
  456.   printf("\n Usage:     UNRAR <command> <archive> <files...>\n");
  457.   printf("\n <Commands>\n");
  458.   printf("\n x       Extract files with full path");
  459.   printf("\n e       Extract files to current directory");
  460.   printf("\n t       Test archive files");
  461.   printf("\n v       Verbosely list contents of archive");
  462.   printf("\n l       List contents of archive");
  463.   printf("\n");
  464. }
  465.  
  466.  
  467. int ExtrFile()
  468. {
  469.   char DestFileName[80];
  470.   long FileCount=0,TotalFileCount=0,DirCount=0,ErrCount=0;
  471.   int ExtrFile=0,Size,SkipSolid=0,UnpSolid;
  472.  
  473.   if ((ArcFPtr=fopen(ArcName,FOPENREADMODE))==NULL)
  474.     ErrExit(EOPEN,FATAL_ERROR);
  475.  
  476.   CheckArc();
  477.   CreateEncTbl(TmpMemory);
  478.   UnpVolume=UnpSolid=0;
  479.   if (MainCommand=='T')
  480.     printf("\n Testing archive %s\n",ArcName);
  481.   else
  482.     printf("\n Extracting from %s\n",ArcName);
  483.  
  484.   while (1)
  485.   {
  486.     Size=ReadBlock(FILE_HEAD);
  487.  
  488.     if (Size<=0 && UnpVolume==0)
  489.       break;
  490.     if ((Lhd.Flags & LHD_SPLIT_BEFORE) && SolidType)
  491.     {
  492.       printf("\nSolid archive: first volume required");
  493.       ErrExit(EEMPTY,FATAL_ERROR);
  494.     }
  495.     if (UnpVolume && Size==0)
  496.       MergeArc(0);
  497.     UnpVolume=(Lhd.Flags & LHD_SPLIT_AFTER);
  498.     fseek(ArcFPtr,NextBlockPos-Lhd.PackSize,SEEK_SET);
  499.  
  500.     TestMode=0;
  501.     ExtrFile=0;
  502.     SkipSolid=0;
  503.  
  504.     if (IsProcessFile(COMPARE_PATH) && (Lhd.Flags & LHD_SPLIT_BEFORE)==0
  505.         || (SkipSolid=SolidType)!=0)
  506.     {
  507.  
  508.       strcpy(DestFileName,ExtrPath);
  509.       strcat(DestFileName,(MainCommand!='E') ? ArcFileName : PointToName(ArcFileName));
  510.  
  511.       ExtrFile=!SkipSolid;
  512.  
  513.       if (Lhd.UnpVer<15 || Lhd.UnpVer>UNP_VER)
  514.       {
  515.         printf("\n %s: unknown method",ArcFileName);
  516.         ExtrFile=0;
  517.         ErrCount++;
  518.         ExitCode=WARNING;
  519.       }
  520.  
  521.       if (Lhd.Flags & LHD_PASSWORD)
  522.       {
  523.         printf("\n %s: cannot process encrypted file",ArcFileName);
  524.         if (SolidType)
  525.           ErrExit(EEMPTY,FATAL_ERROR);
  526.         ExtrFile=0;
  527.         ErrCount++;
  528.         ExitCode=WARNING;
  529.       }
  530.  
  531.       if (Lhd.HostOS==MS_DOS && (Lhd.FileAttr & DOSFA_DIREC))
  532.       {
  533.         if (MainCommand=='E')
  534.           continue;
  535.         if (SkipSolid)
  536.         {
  537.           printf("\n Skipping    %-55s Ok",ArcFileName);
  538.           continue;
  539.         }
  540.         if (MainCommand=='T')
  541.         {
  542.           printf("\n Testing     %-55s Ok",ArcFileName);
  543.           continue;
  544.         }
  545.         CreatePath(DestFileName);
  546.         if (MAKEDIR(DestFileName)==0)
  547.           printf("\n Creating    %-55s",ArcFileName);
  548.         continue;
  549.       }
  550.       else
  551.       {
  552.         if (MainCommand=='T' && ExtrFile)
  553.           TestMode=1;
  554.         if ((MainCommand=='E' || MainCommand=='X') && ExtrFile)
  555.         {
  556.           CreatePath(DestFileName);
  557.           if ((FileFPtr=fopen(DestFileName,FOPENWRITEMODE))==NULL)
  558.           {
  559.             printf("\n Cannot create %s",DestFileName);
  560.             ExitCode=WARNING;
  561.             ExtrFile=0;
  562.           }
  563.         }
  564.       }
  565.  
  566.       if (!ExtrFile && SolidType)
  567.         SkipSolid=TestMode=ExtrFile=1;
  568.       if (ExtrFile)
  569.       {
  570.         TotalFileCount++;
  571.         if (SkipSolid)
  572.           printf("\n Skipping    %-55s",ArcFileName);
  573.         else
  574.         {
  575.           FileCount++;
  576.           switch(MainCommand)
  577.           {
  578.             case 'T':
  579.               printf("\n Testing     %-55s",ArcFileName);
  580.               break;
  581.             case 'X':
  582.             case 'E':
  583.               printf("\n Extracting  %-55s",DestFileName);
  584.               break;
  585.           }
  586.         }
  587.         strcpy(CurExtrFile,DestFileName);
  588.         UnpFileCRC=0xFFFFFFFFL;
  589.         UnpPackedSize=Lhd.PackSize;
  590.         DestUnpSize=Lhd.UnpSize;
  591.         RdUnpFPtr=ArcFPtr;
  592.         WrUnpFPtr=FileFPtr;
  593.         if (Lhd.Method==0x30)
  594.           UnstoreFile();
  595.         else
  596.           if (unpack(TmpMemory,UnpRead,UnpWrite,UnpSolid)==-1)
  597.             ErrExit(EWRITE,WRITE_ERROR);
  598.         if (TotalFileCount>0 && SolidType)
  599.           UnpSolid=1;
  600.         if (UnpFileCRC==~Lhd.FileCRC)
  601.         {
  602.           if (MainCommand!='P')
  603.             printf(" Ok");
  604.         }
  605.         else
  606.         {
  607.           fseek(ArcFPtr,NextBlockPos,SEEK_SET);
  608.           printf("\n %-15s : CRC failed",ArcFileName);
  609.           ExitCode=CRC_ERROR;
  610.           ErrCount++;
  611.         }
  612.         if (!TestMode)
  613.         {
  614.           SETFILETIME(FileFPtr,(void *)&Lhd.FileTime);
  615.           tclose(FileFPtr);
  616.         }
  617.         TestMode=0;
  618.         *CurExtrFile=0;
  619.       }
  620.     }
  621.     if (!ExtrFile && !SolidType)
  622.       fseek(ArcFPtr,NextBlockPos,SEEK_SET);
  623.   }
  624.   tclose(ArcFPtr);
  625.   if ((FileCount+DirCount)==0)
  626.   {
  627.     printf("\n No files");
  628.     ExitCode=WARNING;
  629.   }
  630.   else
  631.     if (ErrCount==0)
  632.       printf("\n  All OK");
  633.     else
  634.       printf("\n  Total errors: %ld",ErrCount);
  635.   return(0);
  636. }
  637.  
  638.  
  639. void ListArchive()
  640. {
  641.   unsigned long TotalPackSize,TotalUnpSize,FileCount;
  642.   int I;
  643.   TotalPackSize=TotalUnpSize=FileCount=0;
  644.   if ((ArcFPtr=fopen(ArcName,FOPENREADMODE))==NULL)
  645.     ErrExit(EOPEN,FATAL_ERROR);
  646.   CheckArc();
  647.   printf("\n ");
  648.   if (SolidType)
  649.     printf("Solid ");
  650.   if (Mhd.Flags & MHD_MULT_VOL)
  651.     printf("%colume ",(SolidType) ? 'v':'V');
  652.   else
  653.     printf("%crchive ",(SolidType) ? 'a':'A');
  654.   printf("%s\n",ArcName);
  655.   if (MainCommand=='V')
  656.     printf("\n Pathname/Comment\n%12.12s","");
  657.   else
  658.     printf("\n Name       ");
  659.   printf("      Size   Packed  Ratio   Date   Time  Attr   CRC-32  Meth Ver\n");
  660.   for (I=0;I<77;I++)
  661.     printf("-");
  662.   while(ReadBlock(FILE_HEAD) > 0)
  663.   {
  664.     if (IsProcessFile(NOT_COMPARE_PATH))
  665.     {
  666.       printf("\n%c",(Lhd.Flags & LHD_PASSWORD) ? '*' : ' ');
  667.       if (MainCommand=='V')
  668.       {
  669.         printf("%-s",ArcFileName);
  670.         printf("\n%12s ","");
  671.       }
  672.       else
  673.         printf("%-12s",PointToName(ArcFileName));
  674.  
  675.       printf(" %8ld %8ld ",Lhd.UnpSize,Lhd.PackSize);
  676.       if (Lhd.Flags & (LHD_SPLIT_AFTER | LHD_SPLIT_BEFORE))
  677.         printf(" Split");
  678.       else
  679.         printf(" %3d%% ",ToPercent(Lhd.PackSize,Lhd.UnpSize));
  680.  
  681.       printf(" %02d-%02d-%02d %02d:%02d ",(int)(Lhd.FileTime>>16) & 0x1f,
  682.         (int)(Lhd.FileTime>>21) & 0xf,(int)((Lhd.FileTime>>25)+1980)%100,
  683.         (int)(Lhd.FileTime>>11) & 0x1f,(int)(Lhd.FileTime>>5) & 0x3f);
  684.  
  685.       if (Lhd.HostOS==MS_DOS)
  686.         printf("%c%c%c%c%c",
  687.           (Lhd.FileAttr & DOSFA_DIREC ) ? 'D' : '.',
  688.           (Lhd.FileAttr & DOSFA_RDONLY) ? 'R' : '.',
  689.           (Lhd.FileAttr & DOSFA_HIDDEN) ? 'H' : '.',
  690.           (Lhd.FileAttr & DOSFA_SYSTEM) ? 'S' : '.',
  691.           (Lhd.FileAttr & DOSFA_ARCH  ) ? 'A' : '.');
  692.       else
  693.         printf("     ");
  694.       printf(" %8.8lX  m%d  %d.%d",Lhd.FileCRC,Lhd.Method-0x30,Lhd.UnpVer/10,Lhd.UnpVer%10);
  695.       if (!(Lhd.Flags & LHD_SPLIT_BEFORE))
  696.       {
  697.         TotalUnpSize+=Lhd.UnpSize;
  698.         FileCount++;
  699.       }
  700.       TotalPackSize+=Lhd.PackSize;
  701.     }
  702.     fseek(ArcFPtr,NextBlockPos,SEEK_SET);
  703.   }
  704.   printf("\n");
  705.   for (I=0;I<77;I++)
  706.     printf("-");
  707.   printf("\n%5ld %16ld %8ld %4d%%\n",FileCount,TotalUnpSize,TotalPackSize,ToPercent(TotalPackSize,TotalUnpSize));
  708.   tclose(ArcFPtr);
  709. }
  710.  
  711.  
  712. int IsProcessFile(ComparePath)
  713. int ComparePath;
  714. {
  715.   int NumName,WildCards;
  716.   char ArgName[80],dir1[80],name1[15],dir2[80],name2[15];
  717.   for (NumName=0;NumName<ArgCount;NumName++)
  718.   {
  719.     memcpy((void *)ArgName,(void *)ArgNames[NumName],sizeof(ArgName));
  720.     WildCards=(strchr(ArgName,'?')!=NULL || strchr(ArgName,'*')!=NULL);
  721.     SplitName(ArgName,dir1,name1);
  722.     SplitName(ArcFileName,dir2,name2);
  723.     if (CmpName(name1,name2) && ((ComparePath==NOT_COMPARE_PATH && *dir1==0) ||
  724.           WildCards && strnicomp(dir1,dir2,strlen(dir1))==0 ||
  725.           strnicomp(dir1,dir2,1000)==0))
  726.       return(1);
  727.   }
  728.   return(0);
  729. }
  730.  
  731. int ReadBlock(BlockType)
  732. int BlockType;
  733. {
  734.   UDWORD HeadCRC;
  735.   UBYTE Header[32];
  736.   int Size,I;
  737.   memset(&Lhd,0,sizeof(Lhd));
  738.   memset(Header,0,sizeof(Header));
  739.   while (1)
  740.   {
  741.     Size=tread(ArcFPtr,Header,32);
  742.     Lhd.HeadCRC  = Header[0] +(UWORD)Header[1]*0x100;
  743.     Lhd.HeadType = Header[2];
  744.     Lhd.Flags    = Header[3] +(UWORD)Header[4]*0x100;
  745.     Lhd.HeadSize = Header[5] +(UWORD)Header[6]*0x100;;
  746.     Lhd.PackSize = Header[7] +(UWORD)Header[8]*0x100+(UDWORD)Header[9]*0x10000L+(UDWORD)Header[10]*0x1000000L;
  747.     Lhd.UnpSize  = Header[11]+(UWORD)Header[12]*0x100+(UDWORD)Header[13]*0x10000L+(UDWORD)Header[14]*0x1000000L;
  748.     Lhd.HostOS   = Header[15];
  749.     Lhd.FileCRC  = Header[16]+(UWORD)Header[17]*0x100+(UDWORD)Header[18]*0x10000L+(UDWORD)Header[19]*0x1000000L;
  750.     Lhd.FileTime = Header[20]+(UWORD)Header[21]*0x100+(UDWORD)Header[22]*0x10000L+(UDWORD)Header[23]*0x1000000L;
  751.     Lhd.UnpVer   = Header[24];
  752.     Lhd.Method   = Header[25];
  753.     Lhd.NameSize = Header[26]+(UWORD)Header[27]*0x100;
  754.     Lhd.FileAttr = Header[28]+(UWORD)Header[29]*0x100+(UDWORD)Header[30]*0x10000L+(UDWORD)Header[31]*0x1000000L;
  755.     if (Size != 0 && (Size<7 || Lhd.HeadSize<7))
  756.       ErrExit(EARCH,FATAL_ERROR);
  757.     NextBlockPos=ftell(ArcFPtr)-Size+Lhd.HeadSize;
  758.     if (Lhd.Flags & LONG_BLOCK)
  759.       NextBlockPos+=Lhd.PackSize;
  760.     if (Size==0 || BlockType==ALL_HEAD || Lhd.HeadType==BlockType)
  761.       break;
  762.     fseek(ArcFPtr,NextBlockPos,SEEK_SET);
  763.   }
  764.   if (Size>0 && BlockType==FILE_HEAD)
  765.   {
  766.     tread(ArcFPtr,ArcFileName,Lhd.NameSize);
  767.     ArcFileName[Lhd.NameSize]=0;
  768.     Size+=Lhd.NameSize;
  769.     HeadCRC=CRC(0xFFFFFFFFL,&Header[2],30);
  770.     if (!(Lhd.HeadCRC==(UWORD)~CRC(HeadCRC,&ArcFileName[0],Lhd.NameSize)))
  771.       printf("\n %s: file header broken\n",ArcFileName);
  772.     for (I=0;ArcFileName[I];I++)
  773.       if (ArcFileName[I]=='\\' || ArcFileName[I]=='/')
  774.         ArcFileName[I]=PATHDIV;
  775.     if (Lhd.HostOS==MS_DOS)
  776.       strtolwr(ArcFileName);
  777.   }
  778.   return(Size);
  779. }
  780.  
  781.  
  782. int UnpRead(Addr,Count)
  783. UBYTE *Addr;
  784. UWORD Count;
  785. {
  786.   int RetCode;
  787.   unsigned int ReadSize,TotalRead=0;
  788.   UBYTE *ReadAddr;
  789.   ReadAddr=Addr;
  790.   while (Count > 0)
  791.   {
  792.     ReadSize=(unsigned int)((Count>UnpPackedSize) ? UnpPackedSize : Count);
  793.     if ((RetCode=fread(ReadAddr,1,ReadSize,RdUnpFPtr))!=ReadSize)
  794.       break;
  795.     TotalRead+=RetCode;
  796.     ReadAddr+=RetCode;
  797.     Count-=RetCode;
  798.     UnpPackedSize-=RetCode;
  799.     if (UnpPackedSize == 0 && UnpVolume)
  800.       MergeArc(1);
  801.     else
  802.       break;
  803.   }
  804.   if (RetCode!=-1)
  805.     RetCode=(int)TotalRead;
  806.   return(RetCode);
  807. }
  808.  
  809.  
  810. int UnpWrite(Addr,Count)
  811. UBYTE *Addr;
  812. UWORD Count;
  813. {
  814.   int RetCode;
  815.   if (TestMode)
  816.     RetCode=(int)Count;
  817.   else
  818.     if ((RetCode=fwrite(Addr,1,Count,WrUnpFPtr))!=Count)
  819.       RetCode = -1;
  820.   if (RetCode!=-1)
  821.     UnpFileCRC=CRC(UnpFileCRC,Addr,(UWORD)RetCode);
  822.   return(RetCode);
  823. }
  824.  
  825.  
  826. UDWORD CRC(StartCRC,Addr,Size)
  827. UDWORD StartCRC;
  828. UBYTE *Addr;
  829. UWORD Size;
  830. {
  831.   UWORD I;
  832.   if (!CRC32_Table[1])
  833.     InitCRC();
  834.   for (I=0;I<Size;I++)
  835.     StartCRC = CRC32_Table[(UBYTE)StartCRC ^ Addr[I]] ^ (StartCRC >> 8);
  836.   return(StartCRC);
  837. }
  838.  
  839. void InitCRC()
  840. {
  841.   int I, J;
  842.   UDWORD C;
  843.   for (I=0;I<256;I++)
  844.   {
  845.     for (C=I,J=0;J<8;J++)
  846.       C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1);
  847.     CRC32_Table[I]=C;
  848.   }
  849. }
  850.