Опубликован: 15.06.2004 | Доступ: свободный | Студентов: 2557 / 712 | Оценка: 4.35 / 3.96 | Длительность: 27:47:00
ISBN: 978-5-9556-0011-6
Лекция 4:

Организация файловой системы

Создание, удаление, копирование и перемещение файлов

Стандарт POSIX-2001 не требует наличия утилиты для создания   обычных файлов. Они появляются по мере необходимости как побочный продукт многочисленных служебных программ (например, утилиты копирования), поэтому сама постановка задачи - создать файл "просто так" - является отчасти надуманной. В то же время, если новый файл все-таки нужен, полезно иметь в виду возможность перенаправления вывода пустой команды, которая имеется в языке shell.

При программировании на языке C для создания   обычных файлов можно воспользоваться функцией creat() (см. листинг 4.30).

#include <fcntl.h>
int creat (const char *path, mode_t mode);
Листинг 4.30. Описание функции creat().

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

Если файл, который пытаются создать при помощи creat(), уже существует, он опустошается (размер становится равным 0), а режим доступа и владелец не изменяются.

В случае неудачи результат creat() равен -1, а внешней переменной errno присваивается код ошибки, позволяющий определить причину ее (ошибки) возникновения. Переменная errno, а также мнемоники для кодов ошибок определены в заголовочном файле   <errno.h>. Для формирования системного сообщения об ошибке можно воспользоваться функцией perror() (см. листинг 4.31), которая, опираясь на значение errno, помещает в стандартный протокол описание последней ошибки.

#include <stdio.h>
void perror (const char *s);
Листинг 4.31. Описание функции perror().

Например, при первом выполнении программы, приведенной в листинге 4.32, в стандартный протокол может быть выдан соответствующий результат (см. листинг 4.33).

#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <limits.h>
/* Программа пытается создавать в текущем  */
/* каталоге файлы с именами g1, g2, ...,   */
/* пока эти попытки не закончатся неудачей */
int main (void) {
 int  n = 0;
 char name [PATH_MAX]; 
 do
   sprintf (name, "g%d", ++n);
 while (creat (name, (mode_t) 0) >= 0);
 perror ("CREAT failed");
 fprintf (stderr, "errno = %d\n", errno);
 fprintf (stderr, 
         "Неудача на файле номер %d\n", n);
 return 0;
}
Листинг 4.32. Пример программы, использующей функции creat() и perror().
CREAT failed: Too many open files
errno = 24
Неудача на файле номер 1022
Листинг 4.33. Возможный результат первого выполнения программы, использующей функции creat() и perror().

Результат второго запуска той же программы показан в листинге 4.34.

CREAT failed: Permission denied
errno = 22
Неудача на файле номер 1
Листинг 4.34. Результат повторного выполнения программы, использующей функции creat() и perror().

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

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

Рассмотренный в примере стиль уведомления о неудачном завершении общий для большинства функций. Неудача определяется возвращением результата, невозможного в другом случае (почти всегда это -1 или пустой указатель NULL ); код ошибки заносится в переменную errno. Разумеется, в реальных программах errno не выводят, а анализируют. В данном случае уместно было бы сравнивать errno с константами EACCES, EINVAL, EMFILE и т.д. (см. <errno.h> ).

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

df = creat ("/tmp/sample", 
            S_IRWXU | S_IRWXG | S_IRWXO);
Листинг 4.35. Пример вызова функции creat().

Для создания (пустых) каталогов служит утилита

mkdir  [-p] [-m режим_доступа]  каталог ...

и функция mkdir()

#include <sys/stat.h>
int mkdir (const char *path, mode_t mode);

С помощью одной команды mkdir можно сформировать несколько каталогов. В каждом из них появятся ссылки . и .., которые другими способами создать нельзя. По умолчанию устанавливаются все биты режима доступа; режим можно задать и явно с помощью опции -m.

Если нужен не один, а целая цепочка каталогов, следует воспользоваться опцией -p. Соответствующий пример приведен в листинге 4.36.

mkdir -p work/tmp/save
Листинг 4.36. Пример использования служебной программы mkdir для создания цепочки каталогов.

По этой команде в текущем каталоге появится подкаталог work, в нем - каталог   tmp, а уже в нем - каталог   save.

Смысл аргументов функции mkdir() тот же, что и для creat(), в случае неудачи возвращается -1, но при нормальном завершении результат равен 0 ( mkdir() не оставляет новый каталог открытым). Перечисленные выше условия неудачного завершения creat() (кроме превышения максимального числа одновременно открытых файлов ) применимы и к mkdir().

Интерфейс, сходный с mkdir, имеют утилита mkfifo для создания каналов:

mkfifo  [-m режим_доступа] канал ...

Заметим, что здесь отсутствует опция -p ) и одноименная функция (см. листинг 4.37).

#include <sys/stat.h>
int mkfifo (const char *path, mode_t mode);
Листинг 4.37. Описание функции mkfifo().
Антон Коновалов
Антон Коновалов

В настоящее время актуальный стандарт - это POSIX 2008 и его дополнение POSIX 1003.13
Планируется ли актуализация материалов данного очень полезного курса?