Чтение онлайн

на главную - закладки

Жанры

Linux программирование в примерах
Шрифт:

1. Если новое имя файла обозначает существующий файл, сначала удалить этот файл.

2. Создать новую ссылку на файл через новое имя.

3. Удалить старое имя (ссылку) для файла. (Удаление имен обсуждается в следующем разделе.)

Ранние версии команды mv работали таким способом. Однако, при таком способе переименование файла не является атомарным; т.е. оно не осуществляется посредством одной непрерываемой операции. И на сильно загруженной системе злонамеренный пользователь мог бы воспользоваться условиями состояния гонки [51] , разрушая операцию переименования и подменяя оригинальный файл другим.

51

Состояние .гонки (race condition) является ситуацией, при которой детали временных соотношений могут вызывать непреднамеренные побочные эффекты или ошибки. В данном случае, каталог в течение короткого периода времени находится в противоречивом состоянии, и именно эта противоречивость и создаёт уязвимость — Примеч. автора.

По этой причине 4.2 BSD ввело системный вызов

rename
:

#include <stdio.h> /* ISO С */

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

На системах Linux операция переименования является атомарной; справочная страница утверждает:

Если

newpath
уже существует, он будет атомарно замещен
..,
таким образом, что при попытке другого процесса получить доступ к
newpath
он никогда не обнаружит его отсутствующим.

Если

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

Как и в случае с другими системными вызовами, возвращенный 0 означает успех, а (-1) означает ошибку.

5.1.5. Удаление файла

Удаление файла означает удаление элемента каталога для файла и уменьшение счетчика ссылок на файл, который содержится в индексе. Содержимое файла и дисковые блоки, в котором оно размешается, не освобождаются до тех пор, пока счетчик ссылок не достигнет нуля.

Системный вызов называется

unlink
:

#include <unistd.h> /* POSIX */

int unlink(const char *pathname);

В нашем обсуждении ссылок на файлы имя имеет смысл; этот вызов удаляет данную ссылку (элемент каталога) для файла. Она возвращает 0 в случае успеха и -1 при ошибке. Возможность удаления файла требует права записи лишь для каталога, а не для самого файла. Этот факт может сбивать с толку, особенно начинающих пользователей Linux/Unix. Однако, поскольку операция в каталоге одна, это имеет смысл; меняется именно содержимое каталога, а не содержимое файла [52] .

52

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

5.1.5.1. Удаление открытых файлов

С самых первых дней Unix было возможно удалять открытые файлы. Просто вызовите

unlink
с именем файла после успешного вызова
open
или
creat
.

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

Ответ — да, вы можете продолжить использовать открытый файл обычным способом. Система знает, что файл открыт, поэтому она откладывает освобождение хранилища файла до тех пор, пока не будет закрыт последний дескриптор файла. Когда файл вообще больше не используется, память освобождается.

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

/* Получение конфиденциального временного хранилища,

проверка ошибок для краткости опущена */

int fd;

mode_t mode = O_CREAT | O_EXCL | O_TRUNC | O_RDWR;

fd = open("/tmp/myfile", mode, 0000); /* Открыть файл */

unlink("/tmp/myfile"); /* Удалить его */

/* ... продолжить использование файла... *

close(fd); /* Закрыть файл, освободить память */

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

5.1.5.2. Использование ISO С:

remove

ISO С предоставляет для удаления файлов функцию

remove
; она предназначена в качестве обшей функции, годной для любой системы, поддерживающей ISO С, а не только для Unix и GNU/Linux:

#include <stdio.h> /* ISO С */

int remove(const char *pathname);

Хотя технически это не системный вызов, возвращаемое значение в том же стиле: 0 в случае успеха и -1 при ошибке, причем

errno
содержит значение ошибки.

В GNU/Linux

remove
использует для удаления файлов системный вызов
unlink
, а для удаления каталогов — системный вызов
rmdir
(обсуждаемый далее в главе). (На более старых системах GNU/Linux, не использующих GLIBC,
remove
является псевдонимом для
unlink
; поэтому для каталогов завершается неудачей. Если у вас такая система, вам, возможно, следует ее обновить.)

5.1.6. Символические ссылки

Мы начали главу с обсуждения разделов, файловых систем и индексов. Мы также увидели, что элементы каталога связывают имена с номерами индексов. Поскольку элементы каталога не содержат другой информации, прямые ссылки ограничены файлами внутри одной и той же файловой системы. Это должно быть; нет способа отличить индекс 2341 одной файловой системы от индекса 2341 другой файловой системы. Вот что случится, если мы попытаемся это сделать:

mount /* Показать использующиеся файловые системы */

Поделиться:
Популярные книги

Законы Рода. Том 6

Андрей Мельник
6. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 6

Газлайтер. Том 27

Володин Григорий Григорьевич
27. История Телепата
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Газлайтер. Том 27

Газлайтер. Том 14

Володин Григорий Григорьевич
14. История Телепата
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Газлайтер. Том 14

Вечный. Книга VII

Рокотов Алексей
7. Вечный
Фантастика:
боевая фантастика
рпг
попаданцы
5.00
рейтинг книги
Вечный. Книга VII

Барон ломает правила

Ренгач Евгений
11. Закон сильного
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Барон ломает правила

Неофит

Листратов Валерий
3. Ушедший Род
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Неофит

Неудержимый. Книга XXVII

Боярский Андрей
27. Неудержимый
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Неудержимый. Книга XXVII

Наследие Маозари 7

Панежин Евгений
7. Наследие Маозари
Фантастика:
боевая фантастика
юмористическое фэнтези
постапокалипсис
рпг
фэнтези
эпическая фантастика
5.00
рейтинг книги
Наследие Маозари 7

Миллионщик

Шимохин Дмитрий
3. Подкидыш
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Миллионщик

Кодекс Охотника. Книга XXXV

Винокуров Юрий
35. Кодекс Охотника
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXXV

#Бояръ-Аниме. Газлайтер. Том 36

Володин Григорий Григорьевич
36. История Телепата
Фантастика:
боевая фантастика
аниме
фэнтези
5.00
рейтинг книги
#Бояръ-Аниме. Газлайтер. Том 36

На границе империй. Том 10. Часть 6

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 10. Часть 6

Лекарь Империи 5

Карелин Сергей Витальевич
5. Лекарь Империи
Фантастика:
городское фэнтези
аниме
героическая фантастика
попаданцы
5.00
рейтинг книги
Лекарь Империи 5

Печать мастера

Лисина Александра
6. Гибрид
Фантастика:
попаданцы
технофэнтези
аниме
фэнтези
6.00
рейтинг книги
Печать мастера