Системное программирование в UNIX средствами Free Pascal

Пример copyfile


Теперь можем закрепить материал на практике. Задача состоит в написании функции copyfile, которая будет копировать содержимое одного файла в другой. Возвращаемое значение должно быть равно нулю в случае успеха или отрицательному числу – в случае ошибки.

Основная логика действий понятна: открыть первый файл, затем создать второй и выполнять чтение из первого файла и запись во второй до тех пор, пока не будет достигнут конец первого файла. И, наконец, закрыть оба файла.

Окончательное решение может выглядеть таким образом:

(* Программа copyfile: скопировать файл name1 в файл name2 *)

uses linux;

const

  BUFSIZE=512;         (* Размер считываемого блока *)

  PERM=0644;           (* Права доступа для нового файла в форме,

                         похожей на восьмеричную *)

(* Скопировать файл name1 в файл name2 *)

function copyfile(name1, name2: string):integer;

var

  infile, outfile: integer; (*дескрипторы файлов*)



  nread: longint;

  buffer: array [0..BUFSIZE-1] of byte; (*буфер для чтения/записи*)

begin

  infile := fdopen (name1, Open_RDONLY);

  if infile=-1 then

  begin

    copyfile:=-1; (*ошибка открытия первого файла*)

    exit;

  end;

  outfile := fdopen (name2, Open_WRONLY or Open_CREAT or Open_TRUNC, octal(PERM));

  if outfile=-1 then

  begin

    fdclose(infile);

    copyfile:=-2; (*ошибка открытия второго файла*)

    exit;

  end;

  (* Чтение из файла name1 по BUFSIZE символов *)

  nread := fdread (infile, buffer, BUFSIZE);

  while nread > 0 do

  begin

    (* Записать buffer в выходной файл. *)

    if fdwrite (outfile, buffer, nread) < nread then

    begin

      fdclose (infile);

      fdclose (outfile);

      copyfile:=-3;          (* ошибка записи *)

      exit;

    end;

    nread := fdread (infile, buffer, BUFSIZE);

  end;

  (*закрываем прочитанные файлы*)

  fdclose (infile);

  fdclose (outfile);

  if (nread = -1) then

    copyfile := -4           (* ошибка при последнем чтении *)




  else                    

    copyfile := 0;              (* все порядке *)

end;

(* Программа для тестирования функции copyfile *)

var

  retcode:integer;

begin

  if paramcount<2 then

  begin

    writeln('Используйте: ',paramstr(0),' файл-источник файл-приемник');

    exit;

  end;

  retcode := copyfile(paramstr(1), paramstr(2));

  case retcode of

     0:  writeln('Файл ',paramstr(1),' успешно скопирован в файл ',paramstr(2));

    -1:  writeln('Ошибка открытия файла ',paramstr(1),' для чтения');

    -2:  writeln('Ошибка открытия файла ',paramstr(2),' для записи');

    -3:  writeln('Ошибка записи в файл ',paramstr(2));

    -4:  writeln('Ошибка чтения из файла ',paramstr(1));

  end;

end.

Теперь функцию copyfile можно вызывать так:

retcode := copyfile('squarepeg', 'roundhole');

Упражнение 2.6. Измените функцию copyfile так, чтобы в качестве ее параметров могли выступать дескрипторы, а не имена файлов. Проверьте работу новой версии программы.

Упражнение 2.7. Если вы умеете работать с аргументами командной строки, используйте одну из процедур copyfile для создания программы mycp, копирующей первый заданный в командной строке файл во второй.


Содержание раздела