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