Скачиваний:
56
Добавлен:
08.01.2014
Размер:
2.6 Mб
Скачать

4.4.3. Чтение каталогов: вызовы readdir и rewinddir

После открытия каталога из него можно начать считывать записи.

Описание

uses linux;

Function ReadDir(dirptr:pdir):pdirent;

Функции readdir должен передаваться допустимый указатель на дескриптор открытого каталога, обычно возвращаемый предшествующим вызовом opendir. При первом вызове readdir в структуру dirent будет считана первая запись в каталоге. В результате успешного вызова указатель каталога переместится на следующую запись.

Когда в результате последующих вызовов readdir достигнет конца каталога, то вызов вернет нулевой указатель. Если в какой-то момент потребуется начать чтение каталога с начала, то можно использовать системный вызов rewinddir, определенный следующим образом:

Описание

uses stdio;

procedure rewinddir(dirptr:pdir);

Следующий после вызова rewinddir вызов readdir вернет первую запись в каталоге, на который указывает переменная dirptr.

В приведенном ниже примере функция my_double_ls дважды выведет на экран имена всех файлов в заданном каталоге. Она принимает в качестве параметра имя каталога и в случае ошибки возвращает значение -1.

uses linux,stdio;

function my_double_ls(name:pchar):integer;

var

dp:PDIR;

d:pdirent;

begin

(* Открытие каталога с проверкой ошибок *)

dp:=opendir (name);

if dp=nil then

begin

my_double_ls:=-1;

exit;

end;

(* Продолжить обход каталога,

* выводя записи в нем, если

* индекс остается допустимым

*)

d:=readdir(dp);

while d<>nil do

begin

if d^.ino<>0 then

writeln(d^.name);

d:=readdir(dp);

end;

(* Вернуться к началу каталога ... *)

rewinddir(dp);

(* ... и снова вывести его содержимое *)

d:=readdir(dp);

while d<>nil do

begin

if d^.ino<>0 then

writeln(d^.name);

d:=readdir(dp);

end;

closedir(dp);

my_double_ls:=0;

end;

Порядок выводимых функцией my_double_ls имен файлов будет совпадать с порядком расположения файлов в каталоге. Если вызвать функцию my_double_ls в каталоге, содержащем три файла abc, bookmark и fred, то ее вывод может выглядеть так:

.

..

fred

bookmark

abc

.

..

fred

bookmark

abc

Второй пример: процедура find_entry

Процедура find_entry будет искать в каталоге следующий файл (или подкаталог), заканчивающийся определенным суффиксом. Она имеет три параметра: имя каталога, в котором будет выполняться поиск, строка суффикса и флаг, определяющий, нужно ли продолжать дальнейший поиск после того, как искомый элемент будет найден.

Процедура find_entry использует процедуру проверки совпадения строк match с целью определения, заканчивается ли файл заданным суффиксом. Процедура match, в свою очередь, вызывает две процедуры из стандартной библиотеки C системы UNIX: функцию strlen, возвращающую длину строки в символах, и функцию strcmp, которая сравнивает две строки, возвращая нулевое значение в случае их совпадения.

uses linux,strings;

function match(s1, s2: pchar):boolean;forward;

function find_entry(dirname:pchar;suffix:pchar;cont:integer):pchar;

const

dp:pdir=nil;

var

d:pdirent;

begin

if (dp = nil) or (cont = 0) then

begin

if dp <> nil then

closedir (dp);

dp:=opendir(dirname);

if dp = nil then

begin

find_entry:=nil;

exit;

end;

end;

d := readdir (dp);

while d <> nil do

begin

if d^.ino = 0 then

continue;

if match (d^.name, suffix) then

begin

find_entry:=d^.name;

exit;

end;

d := readdir (dp);

end;

closedir (dp);

dp := nil;

find_entry:=nil;

end;

function match(s1, s2: pchar):boolean;

var

diff:integer;

begin

diff := strlen (s1) - strlen (s2);

if strlen (s1) > strlen (s2) then

match:=(strcomp (@s1[diff], s2) = 0)

else

match:=false;

end;

Упражнение 4.1. Измените функцию my_double_ls из предыдущего примера так, чтобы она имела второй параметр – целочисленную переменную skip. Если значение skip равно нулю, то функция my_double_ls должна выполняться так же, как и раньше. Если значение переменной skip равно 1, функция my_double_ls должна пропускать все имена файлов, которые начинаются сточки (.).

Упражнение 4.2. В предыдущей главе мы познакомились с использованием системного вызова fstat для получения информации о файле. Структура tstat, возвращаемая вызовом fstat, содержит поле mode, режим доступа к файлу. Режим доступа к файлу образуется при помощи выполнения побитовой операции ИЛИ значения кода доступа с константами, определяющими, является ли этот файл обычным файлом, каталогом, специальным файлом, или механизмом межпроцессного взаимодействия, таким как именованный канал. Наилучший способ проверить, является ли файл каталогом – использовать макрос S_ISDIR:

(* Переменная buf получена в результате вызова fstat *)

if S_ISDIR(buf.mode) then

writeln('Это каталог')

else

writeln('Это не каталог');

Измените процедуру my_double_ls так, чтобы она вызывала fstat для каждого найденного файла и выводила звездочку после каждого имени каталога.

В дополнение к упражнению приведем пример, демонстрирующий остальные S_-функции:

Uses linux;

Var Info : Stat;

begin

if LStat (paramstr(1),info) then

begin

if S_ISLNK(info.mode) then

Writeln ('File is a link');

if S_ISREG(info.mode) then

Writeln ('File is a regular file');

if S_ISDIR(info.mode) then

Writeln ('File is a directory');

if S_ISCHR(info.mode) then

Writeln ('File is a character device file');

if S_ISBLK(info.mode) then

Writeln ('File is a block device file');

if S_ISFIFO(info.mode) then

Writeln ('File is a named pipe (FIFO)');

if S_ISSOCK(info.mode) then

Writeln ('File is a socket');

end;

end.

Соседние файлы в папке Полищук, Семериков. Системное программирование в UNIX средствами Free Pascal