home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / UTILS / ARC-LBR / DIRARC2.PAS < prev    next >
Pascal/Delphi Source File  |  2000-06-30  |  11KB  |  399 lines

  1. program darc2;
  2. {$R-$U-$C-$K-}
  3. {
  4.   Program:      DIRARC.PAS
  5.   Version:      2.0
  6.   Date:         6/1/86
  7.   Author:       Steve Fox, Albuquerque ROS (505)299-5974
  8.   Revision:     David W. Carroll, High Sierra RBBS (209) 296-3534
  9.   Credits:      Based heavily on DARC.PAS and intended as a companion to
  10.                 that program.
  11.   Description:  Display the directory of an archive created by version 4.30
  12.                 or earlier of the ARC utility (copyright 1985 by System
  13.                 Enhancement Associates) in a format similar to the "v"erbose
  14.                 command.  Some minor differences in the computed values of the
  15.                 stowage factors may be noted due to rounding.
  16.   Upadtes: 2.0  Supports ARC512 added modes. Displays mode number as item "T"
  17.                 as well as complete text description of arc mode.
  18.   Language:     Turbo Pascal Version 3.0 and later (either MS-DOS or CP/M).
  19.   Usage:        DIRARC arcname
  20.                 where arcname is the path/file name of the archive file.  If
  21.                 the file extent is omitted, .ARC is assumed.
  22. }
  23. const
  24.   BLOCKSIZE = 128;
  25.   arcmarc   = 26;                      { special archive marker }
  26.   arcver    = 8;                       { archive header version code }
  27.   strlen    = 80;                      { standard string length }
  28.   fnlen     = 12;                      { file name length - 1 }
  29. type
  30.   long      = record                   { used to simulate long (4 byte) integers }
  31.                 l, h : integer
  32.               end;
  33.   Str10     = string[10];
  34.   StrStd    = string[strlen];
  35.   fntype    = array [0..fnlen] of char;
  36.   buftype   = array [1..BLOCKSIZE] of byte;
  37.   heads     = record
  38.                 name   : fntype;
  39.                 size   : long;
  40.                 date   : integer;
  41.                 time   : integer;
  42.                 crc    : integer;
  43.                 length : long
  44.               end;
  45.   hexvalue  = string[2];
  46. var
  47.   endfile   : boolean;
  48.   hdrver    : byte;
  49.   arcptr    : integer;
  50.   arcname,
  51.   extname   : StrStd;
  52.   arcbuf    : buftype;
  53.   arcfile   : file;
  54.  
  55. function hexval(bt : byte) : hexvalue;
  56. { Convert 8 bit value to hex }
  57.   const
  58.     hexcnv : array[0..15] of char = '0123456789ABCDEF';
  59.   begin
  60.     hexval := hexcnv[bt shr 4] + hexcnv[bt and $0F]
  61.   end;
  62.  
  63. function pad(stg : StrStd; i : integer) : StrStd;
  64. { Pad string with spaces to length of i }
  65.   var
  66.     j : integer;
  67.   begin
  68.     j := length(stg);
  69.     FillChar(stg[succ(j)], i - j, ' ');
  70.     stg[0] := chr(i);
  71.     pad := stg
  72.   end;
  73.  
  74. function intstr(n, w: integer): Str10;
  75. { Return a string value (width 'w')for the input integer ('n') }
  76.   var
  77.     stg: Str10;
  78.   begin
  79.     str(n:w, stg);
  80.     intstr := stg
  81.   end;
  82.  
  83. procedure abort(msg : StrStd);
  84. { terminate the program with an error message }
  85.   begin
  86.     writeln('ABORT: ', msg);
  87.     halt
  88.   end;
  89.  
  90. function fn_to_str(var fn : fntype) : StrStd;
  91. { convert strings from C format (trailing 0) to
  92.   Turbo Pascal format (leading length byte). }
  93.   var
  94.     s : StrStd;
  95.     i : integer;
  96.   begin
  97.     s := '';
  98.     i := 0;
  99.     while fn[i] <> #0 do
  100.       begin
  101.         s := s + fn[i];
  102.         i := succ(i)
  103.       end;
  104.     fn_to_str := s
  105.   end;
  106.  
  107. function unsigned_to_real(u : integer) : real;
  108. { convert unsigned integer to real }
  109. { note: INT is a function that returns a REAL!!!}
  110.   begin
  111.     if u >= 0
  112.       then unsigned_to_real := Int(u)
  113.     else if u = $8000
  114.       then unsigned_to_real := 32768.0
  115.       else unsigned_to_real := 65536.0 + u
  116.   end;
  117.  
  118. function long_to_real(l : long) : real;
  119. { convert long integer to a real }
  120. { note: INT is a function that returns a REAL!!! }
  121.   const
  122.     rcon = 65536.0;
  123.   var
  124.     r : real;
  125.     s : (POS, NEG);
  126.   begin
  127.     if l.h >= 0
  128.       then
  129.         begin
  130.           r := Int(l.h) * rcon;
  131.           s := POS
  132.         end
  133.       else
  134.         begin
  135.           s := NEG;
  136.           if l.h = $8000
  137.             then r := rcon * rcon
  138.             else r := Int(-l.h) * rcon
  139.         end;
  140.     r := r + unsigned_to_real(l.l);
  141.     if s = NEG
  142.       then long_to_real := -r
  143.       else long_to_real := r
  144.   end;
  145.  
  146. procedure Read_Block;
  147. { read a block from the archive file }
  148.   begin
  149.     if EOF(arcfile)
  150.       then endfile := TRUE
  151.       else BlockRead(arcfile, arcbuf, 1);
  152.     arcptr := 1
  153.   end;
  154.  
  155. function get_arc : byte;
  156. { read 1 character from the archive file }
  157.   begin
  158.     if endfile
  159.       then get_arc := 0
  160.       else
  161.         begin
  162.           get_arc := arcbuf[arcptr];
  163.           if arcptr = BLOCKSIZE
  164.             then Read_Block
  165.             else arcptr := succ(arcptr)
  166.         end
  167.   end;
  168.  
  169. procedure fread(var buf; reclen : integer);
  170. { read a record from the archive file }
  171.   var
  172.     i : integer;
  173.     b : array [1..strlen] of byte absolute buf;
  174.   begin
  175.     for i := 1 to reclen
  176.       do b[i] := get_arc
  177.   end;
  178.  
  179. function readhdr(var hdr : heads) : boolean;
  180. { read a file header from the archive file }
  181. { FALSE = eof found; TRUE = header found }
  182.   var
  183.     try  : integer;
  184.     name : fntype;
  185.   begin
  186.     try := 10;
  187.     if endfile
  188.       then
  189.         begin
  190.           readhdr := FALSE;
  191.           exit
  192.         end;
  193.     while get_arc <> arcmarc do
  194.       begin
  195.         if try = 0
  196.           then abort(arcname + ' is not an archive');
  197.         try := pred(try);
  198.         writeln(arcname, ' is not an archive, or is out of sync');
  199.         if endfile
  200.           then abort('Archive length error')
  201.       end;
  202.  
  203.     hdrver := get_arc;
  204.     if hdrver < 0
  205.       then abort('Invalid header in archive ' + arcname);
  206.     if hdrver = 0
  207.       then
  208.         begin                          { special end of file marker }
  209.           readhdr := FALSE;
  210.           exit
  211.       end;
  212.     if hdrver > arcver
  213.       then
  214.         begin
  215.           fread(name, fnlen);
  216.           writeln('Cannot handle file ', fn_to_str(name), ' in archive ',
  217.             arcname);
  218.           writeln('You need a newer version of this program.');
  219.           halt
  220.         end;
  221.  
  222.     if hdrver = 1
  223.       then
  224.         begin
  225.           fread(hdr, sizeof(heads) - sizeof(long));
  226.           hdrver := 2;
  227.           hdr.length := hdr.size
  228.         end
  229.       else fread(hdr, sizeof(heads));
  230.  
  231.     readhdr := TRUE
  232.   end;
  233.  
  234. procedure PrintHeading;
  235.   begin
  236.     writeln;
  237.     writeln('Turbo Pascal DIRARC Utility');
  238.     writeln('Version 2.0, 6/1/86');
  239.     writeln('Lists the directory of .ARC files ');
  240.     writeln('created with ARC version 5.12 and earlier');
  241.     writeln
  242.   end;
  243.  
  244. procedure GetArcName;
  245. { get the name of the archive file }
  246.   var
  247.     i : integer;
  248.   begin
  249.     if ParamCount = 1
  250.       then arcname := ParamStr(1)
  251.     else if ParamCount > 1
  252.       then abort('Too many parameters')
  253.       else
  254.         begin
  255.           write('Enter archive filename: ');
  256.           readln(arcname);
  257.           if arcname = ''
  258.             then abort('No file name entered');
  259.           writeln;
  260.           writeln
  261.         end;
  262.     for i := 1 to length(arcname) do
  263.       arcname[i] := UpCase(arcname[i]);
  264.     if pos('.', arcname) = 0
  265.       then arcname := arcname + '.ARC'
  266.   end;
  267.  
  268. function int_time(time : integer) : StrStd;
  269. { Convert integer format time to printable string }
  270.   var
  271.     ampm : char;
  272.     hour, minute : integer;
  273.     line : string[6];
  274.   begin
  275.     minute := (time shr 5) and $003F;
  276.     hour   := time shr 11;
  277.     if hour > 12
  278.       then
  279.         begin
  280.           hour := hour - 12;
  281.           ampm := 'p'
  282.         end
  283.       else ampm := 'a';
  284.     if hour = 0
  285.       then hour := 12;
  286.     line := intstr(hour, 2) + ':' + intstr(minute, 2) + ampm;
  287.     if line[4] = ' '
  288.       then line[4] := '0';
  289.     int_time := line
  290.   end;
  291.  
  292. function int_date(date : integer) : StrStd;
  293. { Convert standard integer format date to printable string }
  294.   const
  295.     month_name : array[1..12] of string[3] =
  296.       ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
  297.   var
  298.     day, month, year : integer;
  299.     line : string[9];
  300.   begin
  301.     day   := date and $001F;
  302.     month := (date shr 5) and $000F;
  303.     year  := (date shr 9 + 80) mod 100;
  304.     if month in [1..12]
  305.       then line := month_name[month]
  306.       else line := '   ';
  307.     line := intstr(day, 2) + ' ' + line + ' ' + intstr(year, 2);
  308.     if line[8] = ' '
  309.       then line[8] := '0';
  310.     int_date := line
  311.   end;
  312.  
  313. procedure open_arc;
  314. { open the archive file for input processing }
  315.   begin
  316.     {$I-} assign(arcfile, arcname); {$I+}
  317.     if IOresult <> 0
  318.       then abort('Cannot open archive file.');
  319.     {$I-} reset(arcfile); {$I+}
  320.     if IOresult <> 0
  321.       then abort('Cannot open archive file.');
  322.     endfile := FALSE;
  323.     Read_Block
  324.   end;
  325.  
  326. procedure close_arc;
  327. { close the archive file }
  328.   begin
  329.     close(arcfile)
  330.   end;
  331.  
  332. procedure directory;
  333.   const
  334.     stowage : array[1..8] of string[8] =
  335.       (' -None- ', ' -None- ', ' Packed ', 'Squeezed', 'LZCrunch', 'LZCrunch',
  336.       'LZW Pack','Dynam LZ');
  337.   var
  338.     i, total_files, sf : integer;
  339.     size_org, size_now, next_ptr, total_length, total_size : real;
  340.     stg_time, stg_date : Str10;
  341.     hdr : heads;
  342.   begin
  343.     writeln('Name          Length    Stowage  T   SF   Size now  Date       Time    CRC');
  344.     writeln('============  ========  ======== =  ====  ========  =========  ======  ====');
  345.     total_files  := 0;
  346.     next_ptr     := 0.0;
  347.     total_size   := 0.0;
  348.     total_length := 0.0;
  349.     open_arc;
  350.     while readhdr(hdr) do
  351.       begin
  352.         extname := fn_to_str(hdr.name);
  353.         total_files := succ(total_files);
  354.         size_org := long_to_real(hdr.length);
  355.         total_length := total_length + size_org;
  356.         size_now := long_to_real(hdr.size);
  357.         total_size := total_size + size_now;
  358.         stg_time := int_time(hdr.time);
  359.         stg_date := int_date(hdr.date);
  360.         if size_org > 0
  361.           then sf := round(100.0 * (size_org - size_now) / size_org)
  362.           else sf := 0;
  363.         writeln(
  364.           pad(extname, 12),
  365.           size_org:10:0,
  366.           stowage[hdrver]:10,
  367.           hdrver:2,
  368.           sf:5, '%',
  369.           size_now:10:0,
  370.           stg_date:11,
  371.           stg_time:8,
  372.           hexval(hi(hdr.crc)):4, hexval(lo(hdr.crc)):2);
  373.         next_ptr := next_ptr + size_now + 29.0;
  374.         i := trunc(next_ptr / 128.0);
  375.         seek(arcfile, i);
  376.         Read_Block;
  377.         arcptr := succ(round(next_ptr - 128.0 * i))
  378.       end;
  379.     close_arc;
  380.     writeln('        ====  ========              ====  ========');
  381.     if total_length > 0
  382.       then sf := round(100.0 * (total_length - total_size) / total_length)
  383.       else sf := 0;
  384.     writeln(
  385.       'Total',
  386.       total_files:7,
  387.       total_length:10:0,
  388.       ' ':10,
  389.       '  ',
  390.       sf:5, '%',
  391.       total_size:10:0)
  392.   end;
  393.  
  394. begin
  395.   PrintHeading;                        { print a heading }
  396.   GetArcName;                          { get the archive file name }
  397.   directory
  398. end.
  399.