3. Теперь оценивающая программа открывает файл и записывает в него данные. Студент создал файл с правами доступа
– rw-rw-rw-
, поэтому это не представляет проблему.
4. Когда оценивающая программа завершает работу, она удаляет временный файл. Однако, у студента все еще есть копия. Например, может быть возможность получения прибыли при заблаговременной продаже своим товарищам их оценок.
Наш пример упрощенный; помимо простого похищения данных с оценками умный (хотя и аморальный) студент мог бы вместо этого изменить данные.
Если бы профессор не проверял результаты работы своей программы дважды, никто бы ничего не узнал.
ЗАМЕЧАНИЕ. Мы не рекомендуем делать что-либо из этого! Если вы студент, не пытайтесь сделать что-либо подобное. Первое и самое главное, это неэтично. Во-вторых, вас могут выгнать из школы. В-третьих, ваши профессора, наверное, не сталь наивны, чтобы использовать
mktemp
в своих программах. Этот пример лишь для иллюстрации!
По приведенным и другим причинам, все три описанные в данном разделе функции не следует никогда использовать. Они существуют в POSIX и GLIBC лишь для поддержки старых программ, которые были написаны до того, как была осознана опасность этих процедур С этой целью системы GNU/Linux генерируют во время компоновки сообщение:
$ cc ch12-mktemp.c -о ch12-mktemp /* Компилировать программу */
/tmp/cc1XCvD9.о(.text+0x35): In function 'main':
: the use of 'mktemp' is dangerous, better use 'mkstemp'
(Мы рассмотрим
mkstemp
в следующем подразделе.)
Если бы в вашей системе не было
mkstemp
, подумайте, как вы могли бы использовать эти интерфейсы для ее эмулирования. (См. также «Упражнения» для главы 12 в конце.)
12.3.2. Создание и открывание временных файлов (хорошо)
Есть две функции, не имеющие проблем состояния гонки. Одна из них предназначена для использования с библиотекой
<stdio.h>
:
#include <stdio.h> /* ISO С */
FILE *tmpfile(void);
Другая функция для использования с системными вызовами на основе дескрипторов файлов:
#include <stdio.h> /* XSI */
int mkstemp(char* template);
tmpfile
возвращает значение
FILE*
, представляющее уникальный открытый временный файл. Файл открывается в режиме "
w+b
".
w+
означает «открыть для чтения и записи, сначала урезав файл», a b означает двоичный, а не текстовый режим. (На системах GNU/Linux или Unix нет разницы, но на других системах есть.) Файл автоматически удаляется, когда закрывается указатель файла; нет способа получить имя файла, чтобы сохранить его содержимое. Программа в
ch12-tmpfile.c
демонстрирует
tmpfile
:
/* ch12-tmpfile.с --- демонстрация tmpfile.
Проверка ошибок для краткости опущена */
#include <stdio.h>
int main(void) {
static char mesg[] =
"Here's lookin' at you, kid!"; /* заменяет "hello, world" */
printf("Got back <%s>\n", buf); /* Вывести полученные данные */
fclose(fp); /* Закрыть файл, закончить */
return 0; /* Все сделано */
}
Возвращенное значение
FILE*
не отличается от любого другого
FILE*
, возвращенного
fopen
. При запуске получаем ожидавшиеся результаты:
$ ch12-tmpfile
Got back <Here's lookin' at you, kid!>
Ранее мы видели, что авторы GLIBC рекомендуют использование функции
mkstemp
:
$ cc ch12-mktemp.с -о ch12-mktemp /* Компилировать программу */
/tmp/cc1XCvD9.о(.text+0x35): In function "main':
: the use of 'mktemp' is dangerous, better use 'mkstemp'
Эта функция похожа на
mktemp
в том, что она принимает имя файла, оканчивающееся на '
ХХХХХХ
', и заменяет эти символы уникальным суффиксом для создания уникального имени файла. Однако, она идет на один шаг дальше. Она создает и открывает файл. Файл создается с доступом 0600 (т.е.
– rw-------
). Таким образом, доступ к файлу может получить только пользователь, запустивший программу.
Более того, и это то, что делает
mkstemp
более безопасной, файл создается с флагом
O_EXCL
, который гарантирует, что файл не существует, и не дает никому больше открыть файл.
Возвращаемое значение является дескриптором открытого файла, который может использоваться для чтения и записи. Для удаления файла после завершения работы с ним должно использоваться имя пути, сохраненное теперь в переданном