Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОСиСП теория 4 семестра - методичка слайдов Бранцевич Петр Юльянович 2009.doc
Скачиваний:
173
Добавлен:
15.06.2014
Размер:
1.75 Mб
Скачать

2.9.3 Чтение информации из каталога

Для того чтобы начать читать содержимое каталога, нужно создать поток каталога (directory stream), представляемый объектом DIR:

#include <sys/types.h>

#include <dirent.h>

DIR *opendir(const char *name);

struct dirent *readdir(DIR *dir);

void rewinddir(DIR *dirptr);

Где структура dirent представлена так:

struct dirent

{ ino_t d_ino;

off_t d_off;

unsigned short d_reclen;

unsigned char d_type;

char d_name[256]; }

Первый системный вызов используется для открытия потока каталога, в качестве параметров которого указывается название каталога, он возвращает указатель на поток каталога. При успешном выполнении возвращается указатель соответственного типа, при ошибке NULL.

Второй системный вызов позволяет читать записи из каталога. В качестве параметра вызова передается указатель на дескриптор открытого файла, а возвращается - указатель на запись.

В структуре dirent POXIS определяет только поле d_name, остальные поля могут модифицироваться, но в основном они такие:

  1. поле идентификатора дескриптора

  2. смещение к следующей записи

  3. длина данной записи

  4. тип файла

  5. имя файла

При ошибке системный вызов возвращает NULL.

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

EBADF – задано недоступное значение аргумента

Это для отличия ситуации, когда доходит до последней записи, и ошибочной ситуации при чтении с каталога.

Третий системный вызов возвращает указатель чтения на первую запись в каталоге.

#include <sys/types.h>

#include <dirent.h>

struct dirent *d;

DIR *dp;

if ((dp=opendir(name))==NULL)

return(-1);

while (d=readdir(dp)) //

{ if (d->d_ino!=0) printf(“%s\n”,d->d_name);

}

rewinddir(dp); //

while (d=readdir(dp))

{ if (d->d_ino!=0) printf(“%s\n”,d->d_name);

}

close(dp);

return(0);

}

Эта программа выводит два раза содержимое каталога (имена файлов в этом каталоге, включая . и ..). Но нужна дополнительная проверка, чтобы число индексных дескрипторов было отлично от 0.

2.9.4 Закрытие каталога

Для закрытия каталога используется встроенный системный вызов:

int closedir(DIR *dir);

Успешный вызов closedir() закрывает поток каталога, переданный при помощи параметра dir, а также соответствующий дескриптор файла и возвращает значение 0. В случае ошибки функция возвращает -1 и присваивает переменной errno значение EBADF – единственный возможный код ошибки, указывающий, что dir не является открытым потоком каталога.

2.10 Создание жестких ссылок

Можно еще создавать жесткую ссылку или еще одно имя для существующего файла:

#include <unistd.h>

int link(const char *oldpath, const char *newpath);

Для одного и того же файла можно создавать несколько имен:

link(“/home/gr1/stud1”, “/home/gr2/stud2”);

Успешный вызов link() создает для пути newpath новую ссылку, указывающую на существующий файл oldpath, и возвращает значение 0. После завершения оба пути, oldpath и newpath, указывают на один и тот же файл, то есть, фактически невозможно сказать, какая из ссылок была «исходной». При ошибке возвращается -1.

EACCESS –у вызывающего процесса отсутствуют разрешения на поиск для компонента пути oldpath или у вызывающего процесса нет разрешений на запись в ката­лог, содержащий newpath.

EEXIST – путь newpath уже существует — системный вызов link () не переопределяет существующие записи каталога.

EFAULT – параметр oldpath или newpath содержит недопустимый указатель.

EIO – произошла внутренняя ошибка ввода-вывода.

ELOOP – при разрешении пути oldpath или newpath встретилось слишком много сим­волических ссылок.

EMLINK – на структуру inode, на которую указывает путь oldpath, уже указывает мак­симально допустимое количество ссылок.

ENAMETOOLONG –слишком длинное значение oldpath или newpath.

ENOENT – компонент oldpath или newpath не существует.

ENOMEM – недостаточно памяти для выполнения данного запроса.

ENOSPC – на устройстве, которому принадлежит newpath, недостаточно свободного про­странства для новой записи каталога.

ENOTDIR – компонент oldpath или newpath не является каталогом.

EPERM – файловая система, которой принадлежит newpath, не допускает создание но­вых жестких ссылок или oldpath является каталогом.

EROFS – newpath принадлежит файловой системе, доступной только для чтения.

EXDEV – пути newpath и oldpath не принадлежат одной и той же подмонтированной системе. (Linux допускает монтирование одной файловой системы в не­скольких точках, но даже в этом случае нельзя создавать жесткие ссылки ме­жду точками монтирования.)