Вопрос:
Обратите внимание, что для целей этого вопроса я буду предполагать, что каталог — это особый вид файла.
Кроме того, я буду предполагать (и, пожалуйста, исправьте меня, если я ошибаюсь), что права на запись в каталог охватывают право создавать новые файлы в указанном каталоге.
std::filesystem::perms
перечисляет следующие виды разрешений, каждое для трех типов операций read
, write
а также execute
:
owner
: Владелец файла.group
: Группа пользователей файла.others
: Каждый? (Не совсем уверен в этом; пожалуйста, исправьте, если не так.)Теперь, как легко видеть, если кто-то хочет знать, имеет ли запущенная программа данное право, эту информацию нетривиально извлечь из них:
Интересно, что в библиотеке не существует какой-либо функции, которая соответствовала бы следующему объявлению функции:
enum FileAction { READ = 1, WRITE = 2, RW = READ|WRITE };
bool canDo(const std::filesystem::path & path, FileAction action);
Как можно реализовать такую функцию?
Конечно, старый добрый способ до C ++ 17 состоял бы в том, чтобы просто попытаться начать чтение / запись и перехватить исключение в случае сбоя. Я хотел бы думать, что библиотека файловой системы должна предложить более элегантное решение.
Меня интересуют ответы, применимые к Windows (XP +) и Linux. Пожалуйста, отметьте, если ваш ответ относится только к одному (даже если следует надеяться, что универсальный ответ существует и его можно найти).
Случай использования: (Запоздало добавлено к ответам «не спрашивай об этом».)
Выяснить в начале игра находится ли его собственный каталог в допустимом состоянии: в конце концов, запускать не нужно, если он все равно потерпит неудачу.
Мы Можно Предположим, что никакая другая программа не будет связываться с установочным каталогом приложения. Если мы не могу, тогда пользователь и его система имеют большие проблемы, чем игра со сбоями а также нам все равно.
Обычно это локальный каталог на физическом диске в персональном компьютере, который не выйдет из строя во время работы (опять же, если это произойдет мы перестаем заботиться). Ни пользователь, ни какая-либо другая программа не будут пытаться переместить файлы из нашего установочного каталога или удалить их или украсть наши разрешения потому что это глупо (или намеренно) и так, если это произойдет, мы перестаем заботиться.
Пока мы все еще заботимся, мы хотим предоставить лучшее усилие ака жадный алгоритм ака обоснованное предположение относительно того, можем ли мы ожидать успешного запуска.
Пользователь может быть непрофессионалом в работе со своей операционной системой и требовать подсказки обеспечить рабочую среду. Мы хотим предоставить все подсказки, которые мы можем и только тогда перестань заботиться, потому что мы приложение, а не ОС и, конечно, не системный администратор.
Мы хотим помочь пользователю, если помощь возможна без особых усилий, потому что мы хороши. Мы не самаритяне и не супергерои, просто милые. У нас также нет никакого интереса, чтобы попытаться перехватить махинации, которые пользователь может намеренно сделать, потому что тогда любые возникающие проблемы по своей вине и поэтому мы перестаем заботиться.
это устоявшаяся практика для игр, чтобы эвристически проверить их установочную директорию на целостность. Steam предлагает это как сервис для всех игр, установленных через него. Star Trek Online, League of Legends, Warframe имеют пусковые установки, которые делают то же самое.
Эти игры обычно проверяют целостность файла, вычисляя (через чтение) хэши их файлов и сравнение их с известными действительными хешами.
Игра, в которой почти все файлы предназначены для модификации пользователем, такие как Dwarf Fortress не могут этого сделать. Это мог, однако проверьте права на чтение файлов, которые должны быть прочитаны, и права на запись в файлы, которые должны быть записаны. Опять же: нет цель манипулировать такими правами во время игры, и поэтому не следует предполагать, что это происходит.
«Просто попробуйте ввод-вывод и обработайте сбои» — все еще лучший подход по нескольким причинам (в порядке убывания скорости, с которой вы столкнетесь в реальном мире):
Ошибка прогнозирования требует воспроизведения всей логики контроля доступа ОС, которая вполне может зависеть от версии. Не изобретай велосипед.
Предсказание неудачи, даже если все сделано идеально, говорит только о сейчас, не то, что случится, когда попытка операции ввода-вывода фактически предпринята. Файловая система является общим ресурсом, и разрешения могут меняться. Это состояние гонки настолько распространено, что имеет собственное имя: TOCTOU (время проверки — время использования)
Ввод-вывод все еще может завершиться сбоем по множеству других причин, не связанных с разрешением (диск был отключен пользователем, сеть вышла из строя, другой процесс использовал все свободное пространство).
В конечном итоге вы не можете избежать обработки отказов, и выполнение как оценки разрешений, так и обработки отказов добавляет сложности без какой-либо выгоды.
Я не знаю, почему вы внесли исключения в микс — просто откройте файл обычным способом (либо fstream
или же fopen
) и проверьте результат. fstream
даст объект с failbit
задавать, fopen
даст NULL
и в обоих случаях errno
может помочь диагностировать причину.
Конечно, старый добрый пре-C ++ 17 способ — это просто попробовать и начать
чтение / запись и перехват исключения, если это не удалось. я бы хотел
думаю, что библиотека файловой системы должна предложить более элегантный
решение.
Нет более «элегантного решения».
Любое такое предполагаемое «решение» будет восприимчивым к Состояние гонки TOCTOU.
Вы не можете надежно проверить разрешение на выполнение X, а затем попытаться выполнить X в отдельной операции.