Использование "r+"
правильно для первой попытки; Если это не удается из-за того, что файл не существует, попробуйте еще раз с "w+"
. Это дает вам файл, открытый для обновления, но не блокирует файл, если он уже существует.
Однако это неоптимально в том смысле, что существует уязвимость TOCTOU (время проверки, время использования) - если файл создается между неудачным открытием с помощью "r+"
и успешным открытием с помощью "w+"
, информация в файле будет потеряна.
Если у вас есть доступ к функциям POSIX, вы можете использовать open()
вместо fopen()
для правильного выполнения работы за одну атомарную попытку, а затем fdopen()
для преобразования дескриптора файла в поток файлов.
FILE *carefully_open(const char *file)
{
int fd = open(file, O_RDWR | O_CREAT, 0644);
FILE *fp = 0;
if (fd >= 0)
fp = fdopen(fd, "r+");
if (fd >= 0 && fp == 0)
close(fd);
return fp;
}
Единственным недостатком этого является то, что он создаст файл через неработающую символическую ссылку. Вы можете избежать этого с помощью флага O_EXCL
, но тогда открытие не удастся, если файл существует. В конце концов вы в конце концов сделаете два звонка на open()
, один с просто O_RDRW
, а второй с O_RDRW | O_CREAT | O_EXCL
, чтобы обезопасить себя от следования прерванных сообщений.
(Что такое неработающая символическая ссылка? Если в текущем каталоге нет файла pqr
, ln -s ./pqr xyz
означает, что xyz
- это поврежденная символическая ссылка, которая будет 'исправлена' путем создания файла 'pqr' с open()
вызов показан.)
Какие у вас были проблемы?