При работе с файлом, важно обеспечить постоянство соответствия между внутренним представлением и реальным содержимым файла. Мы советуем отдавать предпочтение использованию следующих системных вызовов для работы с физическими файлами через открытые дескрипторы, а не их эквивалентов, использующих путь к файлу:
Системный вызов
Использование
fchdir (int fd)
Переходит в дерикторию, представленную fd.
fchmod (int fd, mode_t mode)
Изменяет права доступа к файлу.
fchown (int fd, uid_t uid, gid_t gif)
Изменяет владельца файла.
fstat (int fd, struct stat * st)
Обращается за информацией, содержащейся в индексном дескрипторе физического файла.
ftruncate (int fd, off_t length)
Обрезает существующий файл.
fdopen (int fd, char * mode)
Инициализирует ввод-вывод из уже открытого дескриптора. Это процедура библиотеки stdio, а не системный вызов.
Для этого, естественно, вы должны открыть файл в нужном режиме, вызвав open() (не забудте про третий аргумент при создании нового файла). Подробнее о вызове open() поговорим позже, когда будем обсуждать проблемы с временными файлами.
Мы настаиваем на необходимости проверять возвращаемый код системных вызовов. Например, сошлемся (даже если это не имеет ничего общего с условиями перехвата) на проблему, обнаруженную в старых реализациях /bin/login, где пренебрегали проверкой кода ошибки. Данное приложение автоматически предоставляло доступ с правами root, если не находило файл /etc/passwd. Такое поведение может показаться приемлемым, если дело касается восстановления поврежденной файловой системы. Однако, проверка, что невозможно открыть файл, вместо проверки на существование файла, оказалась менее приемлема. Вызов /bin/login после открытия максимально возможного количества дескрипторов, позволял получить любому пользователю доступ с правами root... Закончим с этим отступлением, которое показывает, насколько важно проверять не только успешно или нет прошел системный вызов, но и код ошибки, перед тем как предпринимать какие-либо действия, связанные с безопасностью системы.