[Back to ARCHIVES SWAG index] [Back to Main SWAG index] [Original]

    {Let me guess, you are trying to list out the files in the RAR archive,
    correct?  Here's how I do it (this is rough, because I am cleaning it up
    from my source because mine handles it a little differently): }

    CONST
      errmsg:array[0..5] of string[49] = (
        'Unable to access specified file',
        'Unexpected end of file',
        'Unexpected read error',
        'Invalid header ID encountered',
        'Can''t find next entry in archive',
        'File is not in RAR archive format');

      method:array[0..21] of string[9] = (
        'Directory',  {* Directory marker *}
        'Unknown! ',  {* Unknown compression type *}
        'Stored   ',  {* No compression *}
        'Packed   ',  {* Repeat-byte compression *}
        'Squeezed ',  {* Huffman with repeat-byte compression *}
        'crunched ',  {* Obsolete LZW compression *}
        'Crunched ',  {* LZW 9-12 bit with repeat-byte compression *}
        'Squashed ',  {* LZW 9-13 bit compression *}
        'Crushed  ',  {* LZW 2-13 bit compression *}
        'Shrunk   ',  {* LZW 9-13 bit compression *}
        'Reduced 1',  {* Probabilistic factor 1 compression *}
        'Reduced 2',  {* Probabilistic factor 2 compression *}
        'Reduced 3',  {* Probabilistic factor 3 compression *}
        'Reduced 4',  {* Probabilistic factor 4 compression *}
        'Frozen   ',  {* Modified LZW/Huffman compression *}
        'Imploded ',  {* Shannon-Fano tree compression *}
        'Imploded ',  {* Shannon-Fano tree compression *}
        'Fastest  ',
        'Fast     ',
        'Normal   ',
        'Good Comp',
        'Best Comp');

    TYPE
      outrec=record   {* output information structure *}
               filename:string[255];             {* output filename *}
               date:integer;                     {* output date *}
               time:integer;                     {* output time *}
               typ:integer;                      {* output storage type *}
               csize:longint;                    {* output compressed size *}
               usize:longint;                    {* output uncompressed size *}
             end;

       rarheaderrec=record
                  b:array[1..7] of byte;
                 end;
       rarfilerec=record
                packsize:longint;
                unpacksize:longint;
                HostOS:byte; { 0 dos 1 os/2 }
                FileCRC:longint;
                mod_time:integer;
                mod_date:integer;
                rarver:byte;
                method:byte;
                fnamesize:integer;
                attr:longint;
               end;

    VAR out:outrec;
        aborted:boolean;

    procedure emsg(message:string);
    begin
      {*  emsg - Display error message
       *}

      writeln;
      writeln('* '+message);
      aborted:=TRUE;
    end;

    function getbyte(var fp:file):char;
    var buf:array[0..0] of char;
        numread:word;
        c:char;
    begin
      if (not aborted) then begin
        blockread(fp,c,1,numread);
        if numread=0 then begin
          close(fp);
          emsg(errmsg[1]);
        end;
        getbyte:=c;
      end;
    end;

    procedure Process_RAR(var fp:file);

    var rar:rarfilerec;
        rh:rarheaderrec;
        rha:array[1..100] of byte;
        buf:array[0..25] of byte;
        h:integer;
        ad:longint;
        numread:word;
        i,stat:integer;
        add2:word;
        c:char;
        add:boolean;

    begin

      while (not aborted) do begin
      {* set up infinite loop (exit is within loop) *}
        add:=FALSE;
        blockread(fp,rh.b[1],5,numread);
        if numread<>5 then emsg(errmsg[2]);
        if (aborted) then exit;
        if not(rh.b[3]=$74) then exit;
        blockread(fp,h,2,numread);
        if numread<>2 then emsg(errmsg[2]);
        if (aborted) then exit;
        blockread(fp,rar,sizeof(rar),numread);
        if numread<>sizeof(rar) then emsg(errmsg[2]);
        if (aborted) then exit;
        out.filename:='';
        for i:=1 to rar.fnamesize do    {* get filename *}
          out.filename[i]:=getbyte(fp);
        out.filename[0]:=chr(rar.fnamesize);
        out.filename:=stripname(out.filename);
        out.date:=rar.mod_date;
        out.time:=rar.mod_time;
        out.csize:=rar.packsize;
        out.usize:=rar.unpacksize;
        case rar.method of
          $30:out.typ:=2;    {* Stored *}
          $31:out.typ:=17;    {* Shrunk *}
          $32:out.typ:=18;
          $33:out.typ:=19;
          $34:out.typ:=20;
          $35:out.typ:=21;
        else begin
            out.typ:=1;    {* Unknown! *}
            end;
        end;

        {place call to routine that displays one file list line using the
         <out> variable}

        {$I-} seek(fp,filepos(fp)+(h-(sizeof(rar)+7+
                    length(out.filename)))); {$I+}
        if (ioresult<>0) then emsg(errmsg[4]);
        if (aborted) then exit;
        {$I-} seek(fp,filepos(fp)+(rar.packsize)); {$I+}
        if (ioresult<>0) then emsg(errmsg[4]);
        if (aborted) then exit;
      end;
    end;

    procedure showrar(infile:string);
    var    rha:array[1..15] of byte;
             c:char;
             h:word;
       numread:word;

    begin
              assign(fp,infile);
              {$I-} reset(fp,1); {$I+}
              if ioresult<>0 then begin end;

              c:=getbyte(fp);  {* determine type of archive *}
              if (c=$52) then begin
                    if (ord(getbyte(fp))<>$61) then emsg(errmsg[5]);
                    if (ord(getbyte(fp))<>$72) then emsg(errmsg[5]);
                    if (ord(getbyte(fp))<>$21) then emsg(errmsg[5]);
                    if (ord(getbyte(fp))<>$1a) then emsg(errmsg[5]);
                    c:=getbyte(fp);
                    c:=getbyte(fp);
                    blockread(fp,rha[1],5,numread); if numread<>5 then
                            abend(abort,next,errmsg[2]);
                    if rha[3]<>$73 then begin
                       emsg(errmsg[2]);
                    end;
                    blockread(fp,h,2,numread);
                    if numread<>2 then emsg(errmsg[2]);
                    blockread(fp,rha[1],6,numread);
                    if numread<>6 then emsg(errmsg[2]);
                    {$I-} seek(fp,filepos(fp)+(h-13)); {$I+}
                    if (ioresult<>0) then emsg(errmsg[4]);
                    writeln('Original Compress  %  Met'+
                            'hod    Date     Time   Filename');
                    writeln('-------- -------- --- '+
                            '--------- -------- ------ ------------');
                    process_RAR(fp);  {* process RAR entry *}

                    { place call to routine that displays any totals or anything
    you          may have compiled }

              end else reset(fp,1);

              close(fp);              {* close file *}

    end;

    This is not a complete unit or program because it is a cut and paste from
    (MANY) different source files of mine... ;)  I display a bunch of different
    archive types and the display routines are all intertwined, so I had to cut
    out the RAR ones to show you here.  I would not suggest reading the file
    byte by byte and trying to convert it.  I would simply do something like
    what I have done here, (I meant this to be an example... not necessarily a
    cut and paste solution) and use the record and blockread in the record.

    Hope this helps somewhat! ;)

    George A. Roberts IV
    Intuitive Vision Software
    ivsoft@ripco.com

[Back to ARCHIVES SWAG index] [Back to Main SWAG index] [Original]