2016-06-10 1 views
1

Вопрос:Каков самый сжатый способ определить, имеет ли сама программа определенное право доступа к файлу?

Обратите внимание, что для целей данного вопроса я буду считать, что каталог представляет собой особый тип файла.

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

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); 

Как такая функция может быть реализована тогда?

Конечно, старый добрый pre-C++ 17 способ просто попытаться начать чтение/запись и поймать исключение, если он не сработает. Хотелось бы подумать, что библиотека Filesystem предложит более элегантное решение.

Меня интересуют ответы, применимые к Windows (XP +) и Linux. Пожалуйста, отметьте, если ваш ответ применим только к одному (даже если нужно надеяться, что универсальный ответ существует и может быть найден).


использования: (запозданием добавил, чтобы предотвратить против «вы не должны спросить это» ответы.)

констатируют в начале Игру ли его собственный каталог находится в допустимом состоянии: В конце концов, не нужно бежать, если он все равно потерпит неудачу.

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

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

До тех пор, как мы по-прежнему заботиться, мы хотим, чтобы обеспечить лучшее усилием аки жадного алгоритм аки догадку, можем ли мы ожидать, чтобы успешно работать.

Пользователь может быть непрофессиональным в работе с их операционной системой, а требует подсказок для обеспечения рабочей среды. Мы хотим предоставить все подсказки, которые мы можем, и только тогда прекратите заботу, потому что мы - приложение, а не ОС и, конечно, не системный администратор.

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

Это хорошо зарекомендовавшая себя практика для игр, чтобы эвристически проверить их каталог установки на предмет целостности. Steam предлагает это как сервис для всех игр, установленных через него. Star Trek Online, League of Legends, Warframe имеют пусковые установки, которые делают то же самое.

Эти игры обычно проверяют целостность файла, вычисляя (через чтение) хэши их файлов и сравнивая их с известными действительными хэшами.

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

+0

@ildjarn: Пожалуйста, отредактируйте с осторожностью и комментариями. Объект вопроса ссылается на теги, которые больше не задаются после редактирования; Я исправил это. Кроме того, мне труднее узнать правильное поведение, если оно остается необъяснимым. – Zsar

+0

Постарайтесь пометить свои вопросы в соответствии с областью знаний вашего ожидаемого ответчика. В этом случае тег 'windows' вряд ли принесет читателям самые современные знания на языках C++, тогда как« файловые системы »могут действительно привлекать экспертов с файловой системой' boost :: filesystem'/'std :: experimental :: filesystem'. 'stl' не является соответствующим тегом, поскольку TS файловой системы не имеет отношения к STL; Однако 'std' является подходящим. Наконец, все теги C++ с версией (например, 'C++ 1z') всегда должны быть помечены как' C++ '. – ildjarn

+0

О, дайте объяснение, подобное этому, для каждого вопроса, который требует перетаскивания, просто несостоятелен. ; -] – ildjarn

ответ

3

«Просто попробуйте ввод/вывод и обработку сбоев» до сих пор является лучшим подход, по нескольким причинам (примерно в порядке убывания скорости вы будете запускать в них в реальном мире):

  1. Предсказание сбоя требует воспроизведения всей логики управления доступом ОС, что вполне может быть зависящим от версии. Не изобретайте велосипед.

  2. Предсказание сбоя, даже если сделано совершенно точно, сообщает вам только , а не то, что произойдет, когда операция ввода-вывода будет предпринята.Файловая система - это общий ресурс, и разрешения могут меняться. Это состояние гонки настолько распространено, что оно имеет свое собственное имя: TOCTOU (время проверки - время использования)

  3. I/O все еще может выйти из-за множества других причин, не связанных с разрешением (диск был отключен пользователем , сеть опустилась, другой процесс исчерпал все свободное пространство).

В конечном счете вы не можете избежать обработки отказа, а выполнение как обработки разрешений, так и сбоев - это сложность без каких-либо преимуществ.

Я не знаю, почему вы добавили исключения в микс - просто откройте файл обычным способом (либо fstream, либо fopen) и проверьте результат. fstream дал бы объект с failbit set, fopen дал бы NULL, и в обоих случаях errno может помочь в диагностике причины.

+0

Теперь давайте узнаем, что исключения для потоков - неправильный путь. Стандарт требует, чтобы он выдавал «отказ», и ни один крупный поставщик не дал полезные сообщения. Boost.Filestream не лучше. И TS Filestream основан на Boost. Таким образом, «классическая» идиома - единственный правильный подход на данный момент. –

+0

Угадайте, что я должен был добавить свой прецедент: если чтение не получается, это фатальная ошибка, иначе «прерывание без диагноза». Если разрешения не установлены при запуске программы, они, вероятно, не будут установлены для доступа к файлам, поэтому может быть создано более подробное сообщение об ошибке - и пользователь не будет предсказуемо потерять свои данные, например. при неудачном сохранении. Библиотека предлагает несколько способов диагностики вероятной ошибки llater_, например. через 'exist' и' is_regular_file'. Доступно ли разрешение на выполнение данной операции, независимо от того, было ли это действительно успешным, является еще одной ценной информацией, которая поможет пользователю. – Zsar

+0

Там также нет волшебной пули. Если произошел сбой извлечения, 'errno' выдаст бесполезное сообщение об ошибке.В идеале код, сохраненный в исключении 'fail', был бы полезен, и тогда вы могли бы сравнить его с [категориями POSIX] (http://en.cppreference.com/w/cpp/header/system_error). Но, как я уже сказал, я не знаю, выходит ли какой-либо поставщик, выходящий за рамки общего сообщения об ошибке. –

0

Конечно, старый добрый пред-C++ 17 способом было бы просто попробовать и начать чтение/запись и поймать исключение, если это не удается. Я хотел бы подумать, что библиотека Filesystem предложит более элегантное решение .

Нет «более элегантного решения».

Любое такое предполагаемое «решение» было бы восприимчивым к TOCTOU race condition.

Вы не можете надежно проверить разрешение X, а затем попытаться выполнить X в отдельной операции.

+0

Существует заметная разница между «Я не разрешаю читать» и «Я не могу читать». Я не думаю, что программа должна ожидать, что файлы в своей собственной установочной директории также изменят разрешение в течение всего срока ее службы - в то время как они могут быть неправильно настроены в первую очередь (UAC). Если разрешение файла изменилось между попытками проверки и доступа, я бы очень классифицировал это как «не ошибка программы», ака «Мне не нужно анализировать эту ошибку». Первоначально неправильные разрешения, однако, являются частым стандартным классом ошибок и раннее обнаружение их - очень желательный подвиг. – Zsar

+1

@Zsar * Существует заметная разница между «Я не разрешаю читать» и «Я не могу читать». * Вот для чего «errno». Если разрешения * могут * изменить - и они * могут * - ваш код ввода-вывода должен обрабатывать проблемы в любом случае, поэтому вы ничего не получите. То, что вы просите, создает ошибку, которая имеет [свою собственную страницу в Википедии] (https://en.wikipedia.org/wiki/Time_of_check_to_time_of_use) с 13 цитатами на ней, и эта ошибка упоминалась * по имени * в обоих ответах полученные в течение нескольких минут после размещения вашего вопроса. Есть причина, по которой компьютеры существуют на протяжении десятилетий, и никто не сделал то, что вы хотите. –

 Смежные вопросы

  • Нет связанных вопросов^_^