programing

디렉토리의 쓰기 가능 여부 결정

codeshow 2023. 8. 5. 11:06
반응형

디렉토리의 쓰기 가능 여부 결정

Python에서 스크립트를 실행하는 사용자가 디렉토리를 쓸 수 있는지 여부를 결정하는 가장 좋은 방법은 무엇입니까?OS 모듈을 사용해야 하기 때문에 *nix 환경에서 실행하고 있습니다.

Christophe가 제안한 것은 좀 더 Pythonic 솔루션이지만, OS 모듈에는 액세스를 확인하는 os.access 기능이 있습니다.

os.access('/path/to/folder', os.W_OK)W_OK는 쓰기, R_OK는 읽기 등입니다.

이것을 제안하는 것은 이상해 보일 수 있지만, 일반적인 파이썬 관용구는

용서를 구하는 것이 허락을 구하는 것보다 쉽습니다.

그 관용구를 따라서, 누군가는 다음과 같이 말할 수 있습니다.

해당 디렉터리에 기록해 보고 권한이 없는 경우 오류를 확인합니다.

를 사용하는 내 솔루션tempfile모듈:

import tempfile
import errno

def isWritable(path):
    try:
        testfile = tempfile.TemporaryFile(dir = path)
        testfile.close()
    except OSError as e:
        if e.errno == errno.EACCES:  # 13
            return False
        e.filename = path
        raise
    return True

업데이트: Windows에서 코드를 다시 테스트한 결과, 문제 22107: tempfile 모듈이 Windows에서 액세스 거부 오류를 잘못 해석합니다.쓰기 불가능한 디렉터리의 경우 코드가 몇 초 동안 중단되고 마지막으로 다음을 던집니다.IOError: [Errno 17] No usable temporary file name found이것이 2171842 사용자가 관찰한 것일 수도 있습니다.유감스럽게도 현재 이 문제가 해결되지 않았기 때문에 이 문제를 해결하려면 다음과 같은 오류도 파악해야 합니다.

    except (OSError, IOError) as e:
        if e.errno == errno.EACCES or e.errno == errno.EEXIST:  # 13, 17

물론 이 경우에도 지연은 여전히 존재합니다.

모드 비트를 확인합니다.

import os, stat

def isWritable(dirname):
  uid = os.geteuid()
  gid = os.getegid()
  s = os.stat(dirname)
  mode = s[stat.ST_MODE]
  return (
     ((s[stat.ST_UID] == uid) and (mode & stat.S_IWUSR)) or
     ((s[stat.ST_GID] == gid) and (mode & stat.S_IWGRP)) or
     (mode & stat.S_IWOTH)
     )

파일 파마만 신경 쓴다면,os.access(path, os.W_OK)당신이 요구하는 것을 해야 합니다.대신 디렉토리에 쓸 수 있는지 여부를 알고 싶다면,open()쓰기 위한 테스트 파일(사전에 존재해서는 안 됨), 캡처 및 검사IOError테스트 파일을 정리합니다.

더 일반적으로 TOCTO 공격(스크립트가 상승된 권한으로 실행되는 경우에만 문제)을 방지하려면 이러한 사전 테스트를 신뢰하지 말고 권한을 삭제하십시오.open()그리고 기대합니다.IOError.

누군가를 위한 예시를 찾다가 우연히 이 스레드를 발견했습니다.구글의 첫 번째 결과를 축하합니다!

사람들은 이 스레드에서 파이썬 방식에 대해 이야기하지만, 간단한 코드 예제는 없습니까?여기 있습니다. 다른 누구든 끼어들 수 있습니다.

import sys

filepath = 'C:\\path\\to\\your\\file.txt'

try:
    filehandle = open( filepath, 'w' )
except IOError:
    sys.exit( 'Unable to write to file ' + filepath )

filehandle.write("I am writing this text to the file\n")

이렇게 하면 쓰기 위해 파일 핸들을 열고 지정된 파일을 다음에 쓸 수 없는 경우 오류와 함께 종료됩니다.이것은 읽기가 훨씬 쉬우며 파일 경로나 디렉터리에서 사전 검사를 수행하는 것보다 훨씬 더 나은 방법입니다. 사전 검사를 실행할 때와 실제로 파일에 쓰기를 시도할 때 사이에 파일을 쓸 수 없게 되는 경우를 방지하기 때문입니다.

크리스토프 D의 답변을 바탕으로 제가 만든 것은 다음과 같습니다.

import os

def isWritable(directory):
    try:
        tmp_prefix = "write_tester";
        count = 0
        filename = os.path.join(directory, tmp_prefix)
        while(os.path.exists(filename)):
            filename = "{}.{}".format(os.path.join(directory, tmp_prefix),count)
            count = count + 1
        f = open(filename,"w")
        f.close()
        os.remove(filename)
        return True
    except Exception as e:
        #print "{}".format(e)
        return False

directory = "c:\\"
if (isWritable(directory)):
    print "directory is writable"
else:
    print "directory is not writable"
 if os.access(path_to_folder, os.W_OK) is not True:
            print("Folder not writable")
 else :
            print("Folder writable")

액세스에 대한 자세한 내용은 여기에서 확인할 수 있습니다.

저는 Argparse를 통해 논쟁을 추가하는 동안 이와 같은 필요성에 부딪혔습니다.에 된 것.type=FileType('w')제가 디렉토리를 찾고 있었기 때문에 제게 도움이 되지 않았습니다.저는 결국 제 문제를 해결하기 위한 저만의 방법을 쓰게 되었습니다.다음은 Argparse 스니펫을 사용한 결과입니다.

#! /usr/bin/env python
import os
import argparse

def writable_dir(dir):
    if os.access(dir, os.W_OK) and os.path.isdir(dir):
        return os.path.abspath(dir)
    else:
        raise argparse.ArgumentTypeError(dir + " is not writable or does not exist.")

parser = argparse.ArgumentParser()
parser.add_argument("-d","--dir", type=writable_dir, default='/tmp/',
    help="Directory to use. Default: /tmp")
opts = parser.parse_args()

이를 통해 다음과 같은 결과가 발생합니다.

$ python dir-test.py -h
usage: dir-test.py [-h] [-d DIR]

optional arguments:
  -h, --help         show this help message and exit
  -d DIR, --dir DIR  Directory to use. Default: /tmp

$ python dir-test.py -d /not/real
usage: dir-test.py [-h] [-d DIR]
dir-test.py: error: argument -d/--dir: /not/real is not writable or does not exist.

$ python dir-test.py -d ~

다시 돌아가서 printopt.dir를 끝에 추가했더니 모든 것이 원하는 대로 작동하는 것 같습니다.

다른 사용자의 권한을 확인해야 하는 경우(네, 질문과 모순된다는 것을 알고 있지만 누군가에게 유용할 수 있습니다), 를 통해 이 작업을 수행할 수 있습니다.pwd모듈 및 디렉터리의 모드 비트.

고지 사항 - POSIX 권한 모델(및 )을 사용하지 않기 때문에 Windows에서는 작동하지 않습니다.pwd모듈은 여기에서 사용할 수 없습니다. 예: *nix 시스템에만 해당되는 솔루션입니다.

디렉터리에는 읽기, 쓰기 및 eXecute의 3비트가 모두 설정되어 있어야 합니다.
예, R은 필수 항목은 아니지만, R이 없으면 디렉토리에 항목을 나열할 수 없습니다(따라서 이름을 알아야 함).반면에 실행은 절대적으로 필요합니다. 사용자가 파일의 inode를 읽을 수 없기 때문에 X 파일이 없는 W 파일도 만들거나 수정할 수 없습니다.자세한 설명은 이 링크를 참조하십시오.

는 마막으로, ▁the▁are로 사용할 수 .stat모듈, 그들의 설명은 inode(7) man에 있습니다.

확인 방법 샘플 코드:

import pwd
import stat
import os

def check_user_dir(user, directory):
    dir_stat = os.stat(directory)

    user_id, group_id = pwd.getpwnam(user).pw_uid, pwd.getpwnam(user).pw_gid
    directory_mode = dir_stat[stat.ST_MODE]

    # use directory_mode as mask 
    if user_id == dir_stat[stat.ST_UID] and stat.S_IRWXU & directory_mode == stat.S_IRWXU:     # owner and has RWX
        return True
    elif group_id == dir_stat[stat.ST_GID] and stat.S_IRWXG & directory_mode == stat.S_IRWXG:  # in group & it has RWX
        return True
    elif stat.S_IRWXO & directory_mode == stat.S_IRWXO:                                        # everyone has RWX
        return True

    # no permissions
    return False

stat 개체가 읽을 수 있는지 또는 쓸 수 있는지 확인

파이프가 읽을 수 있는지 또는 쓸 수 있는지 확인하는 데 유용합니다.

import os, stat

def check_access(s, check="r"):
  "check if s=os.stat(path) is readable or writable"
  u = os.geteuid(); g = os.getegid(); m = s.st_mode
  if check == "r":
    return (
      ((s[stat.ST_UID] == u) and (m & stat.S_IRUSR)) or
      ((s[stat.ST_GID] == g) and (m & stat.S_IRGRP)) or
      (m & stat.S_IROTH)
    ) != 0
  if check == "w":
    return (
      ((s[stat.ST_UID] == u) and (m & stat.S_IWUSR)) or
      ((s[stat.ST_GID] == g) and (m & stat.S_IWGRP)) or
      (m & stat.S_IWOTH)
    ) != 0

s = os.stat(0) # fd 0 == stdin
print(f"fd 0 is readable?", check_access(s, "r"))

s = os.stat(1) # fd 1 == stdout
print(f"fd 1 is writable?", check_access(s, "w"))

os.write(1, b"hello\n")

Joe Koberg의 답변에.

참고 항목: Javascript에서도 동일한 항목

아마도 창문이 깨졌을 것입니다.

언급URL : https://stackoverflow.com/questions/2113427/determining-whether-a-directory-is-writeable

반응형