Эквивалент Python для чтения файлов Perl (-r), записываемых (-w) и исполняемых (-x) операторов
Я был Google, чтобы попытаться найти эквивалент в Python некоторым из операторов проверки файлов Perl.
Большинство операторов тестовых файлов - это просто прямое питонирование основного вызова os 'stat
. Например, os.stat('file').st_ctime
просто считывает время изменения inode в качестве утилиты * nix stat
или ls -l
.
Некоторые из операторов проверки файлов Perl я не могу найти эквивалент в Python. Например, у меня есть дерево данных из 85 000 файлов изображений, созданных различными приложениями. Некоторые из файлов имеют эффективный UID, установленный таким образом, который является nettlesome и сбой модификации для проблемы разрешения. Поэтому для этих файлов мне нужно запустить что-то вроде:
$ find . -type f -print0 | perl -0 -lnE 'say unless -w' | change euid...
Так как я не нашел эквивалент в Python, мне нужно выложить на Perl, чтобы найти эти файлы. Я нашел эту таблицу, которая предполагает отсутствие прямого эквивалента. Правда?
Ответы
Ответ 1
Глядя на вывод strace
, perl выполняет вызов stat()
, за которым следует getgroups()
, чтобы получить идентификаторы дополнительных групп процесса perl. Похоже, он просто проверяет результаты вызова stat()
против идентификаторов EUID, EGID и дополнительных групп.
Python имеет функцию getgroups()
в os
, поэтому я уверен, что вы можете сделать то же самое.
EDIT: вы можете попробовать что-то подобное, если никто не придет к лучшему ответу. (Жестко проверено):
def effectively_readable(path):
import os, stat
uid = os.getuid()
euid = os.geteuid()
gid = os.getgid()
egid = os.getegid()
# This is probably true most of the time, so just let os.access()
# handle it. Avoids potential bugs in the rest of this function.
if uid == euid and gid == egid:
return os.access(path, os.R_OK)
st = os.stat(path)
# This may be wrong depending on the semantics of your OS.
# i.e. if the file is -------r--, does the owner have access or not?
if st.st_uid == euid:
return st.st_mode & stat.S_IRUSR != 0
# See comment for UID check above.
groups = os.getgroups()
if st.st_gid == egid or st.st_gid in groups:
return st.st_mode & stat.S_IRGRP != 0
return st.st_mode & stat.S_IROTH != 0
Очевидно, что -w будет почти идентичным, но с W_OK, S_IWUSR и т.д.
Ответ 2
Начиная с Python 3.3 вы можете сделать это с помощью os.access
:
Изменено в версии 3.3: Добавлены dir_fd, effective_ids и follow_symlinks.
Если значение effective_ids равно True, access() выполнит проверку доступа используя эффективный uid/gid вместо реального uid/gid. effective_ids может не поддерживаться на вашей платформе; вы можете проверить, действительно ли это доступен с помощью os.supports_effective_ids. Если он недоступен, используя его, вы получите NotImplementedError.
Ответ 3
Чтобы проверить, может ли ваш эффективный пользователь писать файл, большинство просто откроет его и попытается, и поймает ошибку в исключении. Возможно, это не правильное решение во всех случаях, но объясняет, почему для этого нет конкретной поддержки.
Ответ 4
os.access
делает именно то, что вы хотите.
Используйте реальный uid/gid для проверки доступа к пути. Обратите внимание, что в большинстве операций будет использоваться эффективный uid/gid, поэтому эту процедуру можно использовать в среде suid/sgid, чтобы проверить, имеет ли вызывающий пользователь указанный путь к пути.