home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / lan / netcpy30 / cp.pas < prev    next >
Pascal/Delphi Source File  |  1987-08-11  |  7KB  |  310 lines

  1.  
  2. (*
  3.  * cp - unix like file copy
  4.  *
  5.  * shs 8/5/85
  6.  * version 2, shs 5/14/86
  7.  * version 3, shs 8/10/87
  8.  *
  9.  *
  10.  * (C) 1987 Samuel H. Smith, 8/5/85 (rev. 10-Aug-87)
  11.  *
  12.  * This program is provided courtesy of:
  13.  *         The Tool Shop
  14.  *         Phoenix, Az
  15.  *         (602) 279-2673
  16.  *
  17.  * This program uses many of the building-blocks in the Tool Shop Library,
  18.  * which is available for download from the Tool Shop.   Compile using
  19.  * TSHELL 1.2, also available from the Tool Shop.
  20.  *
  21.  *
  22.  * Disclaimer
  23.  * ----------
  24.  *
  25.  * This software is completely FREE.   I ask only for your comments,
  26.  * suggestions and bug reports.   If you modify this program, I would
  27.  * appreciate a copy of the new source code.   Please don't delete my
  28.  * name from the program.
  29.  *
  30.  * I cannot be responsible for any damages resulting from the use or mis-
  31.  * use of this program!
  32.  *
  33.  * If you have any questions, bugs, or suggestions, please contact me at
  34.  * The Tool Shop,  (602) 279-2673.
  35.  *
  36.  * Enjoy!     Samuel H. Smith
  37.  *
  38.  *
  39.  *)
  40.  
  41.  
  42. const
  43.    version = 'CP - Unix-like file copy, (v3.0, SYSTEM_DATE)';
  44.    buf_size = $8000;
  45.  
  46.  
  47. type
  48.    anystring = string[80];
  49.  
  50.  
  51. #include <regpack.inc>    {DOS register package}
  52. #include <dosio.inc>      {DOS I/O function library}
  53. #include <getfiles.inc>   {Get file list from wildcard}
  54. #include <int2real.inc>   {Convert unsigned int to real}
  55. #include <tolower.inc>    {Convert string to lower case}
  56.  
  57.  
  58. var
  59.    buf:      array[0..$7FFF] of byte;
  60.    cur_dir:  anystring;
  61.  
  62.  
  63.  
  64. procedure translate(var str: anystring; old: char; new: char);
  65. var
  66.    i: integer;
  67. begin
  68.    for i := 1 to length(str) do
  69.       if str[i] = old then
  70.          str[i] := new
  71.       else
  72.          str[i] := upcase(str[i]);
  73. end;
  74.  
  75.  
  76. procedure makepath(var name: anystring; dir: anystring);
  77. var
  78.    i:    integer;
  79.    rest: anystring;
  80.  
  81. begin
  82.  
  83. (* make sure device is specified in pathname *)
  84.    if name[1] = '/' then
  85.       name := copy(dir,1,2) + name
  86.    else
  87.  
  88. (* make sure pathname is absolute *)
  89.    if name[2] <> ':' then
  90.       name := dir + name;
  91.  
  92. (* remove references to current directory *)
  93.    i := pos('/./',name);
  94.    while i > 0 do
  95.    begin
  96.       name := copy(name,1,i) + copy(name,i+3,length(name));
  97.       i := pos('/./',name);
  98.    end;
  99.  
  100. (* remove references to parent directory *)
  101.    i := pos('/../',name);
  102.    while i > 0 do
  103.    begin
  104.       rest := copy(name,i+4,length(name));
  105.       i := i - 1;
  106.  
  107.       while (name[i] <> '/') and (i > 2) do
  108.          i := i - 1;
  109.  
  110.       name := copy(name,1,i) + rest;
  111.  
  112.       i := pos('/../',name);
  113.    end;
  114.  
  115. (* change absolute into relative if possible *)
  116.    if copy(name,1,length(cur_dir)) = cur_dir then
  117.       name := copy(name,length(cur_dir)+1,length(name));
  118. end;
  119.  
  120.  
  121. procedure copyfile(input: anystring;  output: anystring);
  122. var
  123.    infd:    integer;
  124.    outfd:   integer;
  125.    length:  real;
  126.    total:   real;
  127.    incnt:   integer;
  128.    outcnt:  integer;
  129.    time:    integer;
  130.    date:    integer;
  131.  
  132. begin
  133.  
  134.    if input = output then
  135.    begin
  136.       writeln;
  137.       writeln('cp: input and output names must be different');
  138.       exit;
  139.    end;
  140.  
  141.    infd := dos_open(input, open_read);
  142.  
  143.    dos_file_times(infd, time_get, time, date);
  144.  
  145.    length := dos_lseek(infd, seek_end, 0);
  146.  
  147.    if dos_lseek(infd, seek_start, 0) <> 0 then
  148.    begin
  149.       writeln;
  150.       writeln('cp: input seek error');
  151.       halt;
  152.    end;
  153.  
  154.    outfd := dos_create(output, 0);
  155.    if outfd = dos_error then
  156.    begin
  157.       writeln;
  158.       writeln('cp: can''t create output');
  159.       halt;
  160.    end;
  161.  
  162.  
  163.    total := 0;
  164.    repeat
  165.       incnt := dos_read(infd, buf, buf_size);
  166.  
  167.       if incnt <> 0 then
  168.       begin
  169.          outcnt := dos_write(outfd, buf, incnt);
  170.          total := total + int_to_real(outcnt);
  171.          write('.');
  172.       end;
  173.  
  174.    until (incnt <> buf_size);
  175.  
  176.    if total <> length then
  177.    begin
  178.       writeln;
  179.       writeln('cp: copy size error');
  180.       halt;
  181.    end;
  182.  
  183.    if dos_close(infd) = dos_error then
  184.    begin
  185.       writeln;
  186.       writeln('cp: input close failed');
  187.       halt;
  188.    end;
  189.  
  190.    dos_file_times(outfd, time_set, time, date);
  191.  
  192.    if dos_close(outfd) = dos_error then
  193.    begin
  194.       writeln;
  195.       writeln('cp: output close failed');
  196.       halt;
  197.    end;
  198. end;
  199.  
  200.  
  201. procedure procfile(source:   anystring;
  202.                    dest:     anystring);
  203. var
  204.    outfile:    file;
  205.    infile:     file;
  206.    outname:    anystring;
  207.    bufcnt:     integer;
  208.    i:          integer;
  209.    len:        integer;
  210.  
  211. begin
  212.  
  213.    translate(source,'\','/');
  214.    outname := '';              {build destination filename}
  215.    i := length(source);
  216.    while (i > 0) and (source[i] <> '/') and (source[i] <> ':') do
  217.    begin
  218.       outname := source[i] + outname;
  219.       i := i - 1;
  220.    end;
  221.  
  222.    len := length(outname);
  223.  
  224.    makepath(outname,dest);
  225.  
  226.    source := tolower(source);
  227.    outname := tolower(outname);
  228.    write(source,'':12-len,' -> ', outname,' ','':12-len);
  229.  
  230.    copyfile(source, outname);
  231.  
  232.    writeln;
  233.  
  234. end;
  235.  
  236.  
  237. procedure procparam(pattern: anystring;
  238.                     dest:    anystring);
  239. var
  240.    i:   integer;
  241.  
  242. begin
  243.    translate(dest,'\','/');
  244.    if (dest[length(dest)] <> '/') and
  245.       (dest[length(dest)] <> ':') then
  246.          dest := dest + '/';
  247.    makepath(dest,cur_dir);
  248.  
  249.    translate(pattern,'\','/');
  250.    makepath(pattern,cur_dir);
  251.  
  252.    translate(pattern,'/','\');
  253.    getfiles(pattern,filetable,filecount);
  254.  
  255.    for i := filecount downto 1 do
  256.       procfile(filetable[i],dest);
  257. end;
  258.  
  259.  
  260. procedure usage;
  261. begin
  262.    writeln;
  263.    writeln(version);
  264.    writeln('Courtesy of:  S.H.Smith  and  The Tool Shop BBS,  (602) 279-2673.');
  265.    writeln;
  266.    writeln('Usage:');
  267.    writeln('  cp SOURCE DEST');
  268.    writeln('  cp SOURCE1 SOURCE2 ... SOURCEn DEST');
  269.    writeln('  cp SOURCE');
  270.    writeln;
  271.    writeln('Examples:');
  272.    writeln('  cp a:*.arc             ;copies all .arc files into current dir');
  273.    writeln('  cp /pcb/main/*.* /pcb/gen/*.* d:/backup');
  274.    writeln;
  275.    writeln('Cp works just like the DOS copy command, with the following exceptions:');
  276.    writeln('  - Both / and \ are allowed as directory delimiters');
  277.    writeln('  - Multiple source files may be specified');
  278.    writeln('  - Network file sharing is supported');
  279.    writeln('  - Files cannot be renamed during a copy (I.E. DEST must be a directory)');
  280.    flush(output);
  281.    halt(1);
  282. end;
  283.  
  284.  
  285. var
  286.    i:     integer;
  287.    dest:  anystring;
  288.  
  289. begin
  290.    clreol;
  291.  
  292.    if paramcount = 0 then
  293.       usage;
  294.  
  295.    getdir(0,cur_dir);
  296.    translate(cur_dir,'\','/');
  297.    if cur_dir[length(cur_dir)] <> '/' then
  298.       cur_dir := cur_dir + '/';
  299.  
  300.    if paramcount = 1 then
  301.       procparam(paramstr(1),'.')
  302.    else
  303.  
  304.    for i := 1 to paramcount-1 do
  305.       procparam(paramstr(i),paramstr(paramcount));
  306.  
  307.    flush(output);
  308. end.
  309.  
  310.