Если счетчик становится равен нулю и файл не открыт ни в одном процессе, он удаляется. В действительности элемент каталога всегда удаляется немедленно, а место, занятое содержимым файла, не очищается до тех пор, пока последний процесс (если таковой существует) не закроет файл. Этот вызов использует программа rm
. Дополнительные ссылки, предоставляющие альтернативные имена файла, обычно создаются программой ln
. Вы можете программно создать новые ссылки на файл с помощью системного вызова link
.
Создание файла с помощью вызова open
и последующее обращение к unlink
для этого файла — трюк, применяемый некоторыми программистами для создания временных или транзитных файлов. Эти файлы доступны программе, только пока они открыты; и будут удалены автоматически, когда программа завершится, и файлы будут закрыты.
Системный вызов link
создает новую ссылку на существующий файл path1
. Новый элемент каталога задается в path2
. Символические ссылки можно создавать аналогичным образом с помощью системного вызова symlink
. Имейте в виду, что символические ссылки на файл не увеличивают значение счетчика ссылок и таким образом, в отличие от обычных (жестких) ссылок, не мешают удалению файла.
Вы можете создавать и удалять каталоги, применяя системные вызовы mkdir
и rmdir
.
#include
int mkdir(const char *path, mode_t mode);
Системный вызов mkdir
используется для создания каталогов и эквивалентен программе mkdir
. Вызов mkdir
формирует новый каталог с именем, указанным в параметре path
. Права доступа к каталогу передаются в параметре mode и задаются как опция о O_CREAT
в системном вызове open и также зависят от переменной umask
.
#include
int rmdir(const char *path);
Системный вызов rmdir
удаляет каталоги, но только если они пустые. Программа rmdir
использует этот системный вызов для выполнения аналогичной работы.
Программа может перемещаться по каталогам во многом так же, как пользователь перемещается по файловой системе. Как вы применяете в командной оболочке команду cd
для смены каталога, так и программа может использовать системный вызов chdir
.
#include
int chdir(const char *path);
Программа может определить свой текущий рабочий каталог, вызвав функцию getcwd
.
#include
char *getcwd(char *buf, size_t size);
Функция getcwd
записывает имя текущего каталога в заданный буфер buf
. Она возвращает NULL
, если имя каталога превысит размер буфера (ошибка ERANGE
), заданный в параметре size
. В случае успешного завершения она возвращает buf
.
Функция getcwd
может также вернуть значение NULL
, если во время выполнения программы каталог удален (EINVAL
) или изменились его права доступа (EACCESS
).
Просмотр каталогов
Широко распространенная проблема систем Linux — просмотр каталогов, т.е. определение файлов, размещенных в конкретном каталоге. В программах командной оболочки она решается легко — просто скомандуйте оболочке выполнить подстановку в выражении с метасимволами. В прошлом в разных вариантах UNIX был разрешен программный доступ к низкоуровневой структуре файловой системы. Вы все еще можете открывать каталог как обычный файл и непосредственно считывать элементы каталога, но разные структуры файловых систем и реализации сделали такой подход непереносимым с машины на машину. Был разработан стандартный комплект библиотечных функций, существенно упрощающий просмотр каталогов.
Функции работы с каталогами объявлены в заголовочном файле dirent.h. В них используется структура DIR
как основа обработки каталогов. Указатель на эту структуру, называемый потоком каталога (DIR*
), действует во многом так же, как действует поток файла (FILE*
) при работе с обычным файлом. Элементы каталога возвращаются в структурах dirent, также объявленных в файле dirent.h, поскольку никому не следует изменять поля непосредственно в структуре DIR
.
Мы рассмотрим следующие функции:
opendir
, closedir
;
readdir
;
telldir
;
seekdir
;
closedir
.
Функция opendir
открывает каталог и формирует поток каталога. Если она завершается успешно, то возвращает указатель на структуру DIR
, которая будет использоваться для чтения элементов каталога.
#include
#include
DIR *opendir(const char *name);