Эти два фрагмента кода не идентичны и дают существенно разные результаты.
Во-первых, ваш статистический вызов проверяет только биты разрешения владельца. Если пользователь, выполняющий этот код, не владеет рассматриваемым файлом, это неправильный набор битов для проверки.
Во-вторых, даже если мы предполагаем, что вызывающий пользователь является владельцем, нам также необходимо выяснить, что мы подразумеваем под «вызывающим пользователем». Что касается open(2)
и его друзей, то вызывающим пользователем является номер, возвращаемый geteuid(2)
, то есть эффективный идентификатор пользователя . Это то, что open использует, чтобы определить, разрешить ли открытие файла. Что касается access(2)
, то вызывающим пользователем является номер, возвращаемый getuid(2)
, то есть реальный идентификатор пользователя . Это то, что использует доступ, чтобы определить, следует ли сообщать об успехе. Действительные и эффективные идентификаторы UID могут различаться, особенно при запуске двоичного файла с включенным битом setuid или когда программист делает что-то особенно умное (и, вероятно, ИМХО опрометчивое).
(Между тем, stat()
не заботится о вызывающем пользователе так или иначе, за исключением того, что для выполнения своей работы ему требуется разрешение на выполнение в содержащем каталоге. Для этого он проверяет EUID).
Наконец, как было указано в нескольких ответах, оба фрагмента кода могут быть уязвимы для ошибок TOCTTOU , в зависимости от того, что вы делаете с результатами. В общем, самый безопасный способ определить, разрешено ли действие, - это попытаться выполнить это действие и проверить, не выполнено ли оно.