如何在MS XP/Vista上检查是否可以在给定目录中创建文件?

6
我有一段代码,可以在用户指定的目录中创建文件。用户可能会指向一个无法创建文件但可以重命名的目录。
我为测试目的创建了一个目录,称之为C:\foo
我对C:\foo具有以下权限:
遍历目录/执行文件
删除子文件夹和文件
删除
读取权限
更改权限
拥有权
我没有以下权限:
完全控制
文件创建
文件夹创建
到目前为止,我尝试了以下方法: os.access('C:\foo', os.W_OK) == True st = os.stat('C:\foo') mode = st[stat.ST_MODE] mode & stat.S_IWRITE == True 我认为这是因为我可以重命名文件夹,所以它对我而言是可更改的,但它的内容不是。
有人知道如何编写代码来检查给定目录的当前用户是否具有在该目录中创建文件的权限吗?
简而言之,我想检查当前用户是否具有给定文件夹名称的文件创建和文件夹创建权限。
需要这样的代码的原因是来自“经过Windows Vista认证”的程序的第3个测试用例,其中规定:
应用程序不得允许最低特权用户将任何文件保存到Windows系统目录中,以通过此测试用例。
这是否应理解为“应用程序可以尝试将文件保存在Windows系统目录中,但不应在失败时崩溃?”还是“应用程序必须在尝试保存文件之前执行安全检查?”
4个回答

4
我不会浪费时间和代码行数来检查权限。在Windows中,文件创建的最终测试就是创建本身。其他因素可能会产生影响(例如同名的现有文件(或更糟糕的是文件夹),磁盘空间,后台进程等)。这些条件甚至可能在您进行初始检查和实际尝试创建文件之间发生变化。
因此,如果我遇到这样的情况,我会设计我的方法,在失败的情况下不丢失任何数据,继续尝试创建文件,并为用户提供更改所选目录并重试的选项。

目前应用程序不会在这种情况下崩溃,只会显示一个操作失败的弹窗。但我真正需要的是通过“Certified for Windows Vista”测试 - 请参见编辑后的问题。 - Abgan
我认为测试用例意味着应用程序不应包含权限提升漏洞或尝试规避标准安全以允许该操作。除此之外,目录安全应由操作系统负责。 - Ishmaeel

4
我最近编写了一个应用程序,通过一组测试来获取 Microsoft 的 ISV 状态,并添加了该条件。根据我的理解,如果用户只拥有 Least Priveledge 权限,则不具备在系统文件夹中写入的权限。因此,我按照 Ishmaeel 的描述方式解决了这个问题。我试图创建文件并捕获异常,然后告知用户他没有权限将文件写入该目录。
在我看来,最低权限用户将无法写入这些文件夹,如果他可以进行写入,则不是最低权限用户。

我应该停止烦恼吗?因为 Windows Vista 本身不允许最低权限用户在 %WINDIR% 中保存任何文件?

在我看来,是的。

谢谢。我会遵循你和伊斯梅尔的建议。 - Abgan

3

我同意其他答案的观点,做法是尝试创建文件并捕获异常。

然而,在Vista上要注意UAC!例如,请参见“为什么我的应用程序允许我在Vista中将文件保存到Windows和System32文件夹?”:为了支持旧应用程序,Vista将“假装”创建文件,而实际上它会在当前用户配置文件下的所谓虚拟存储中创建它。

为了避免这种情况,您必须明确告诉Vista您不想要管理员权限,通过在.exe的清单中包含适当的命令,参见上面链接的问题。


谢谢你的提醒,但是所涉及的应用程序已经将执行级别设置为“asInvoker”,所以我不应该遇到UAC :-) - Abgan

3
import os
import tempfile

def can_create_file(folder_path):
    try:
        tempfile.TemporaryFile(dir=folder_path)
        return True
    except OSError:
        return False

def can_create_folder(folder_path):
    try:
        name = tempfile.mkdtemp(dir=folder_path)
        os.rmdir(name)
        return True
    except OSError:
        return False

如果用户没有删除目录的权限,但有创建目录的权限,则您的can_create_folder()函数会失败。 而且应该捕获IOError而不是OSError吧?我收到了带错误号13的IOError。 除此之外,代码还是不错的,但当创建实际文件时我必须捕获IOError(因为存在竞争条件)。 - Abgan
请注意,Python 3.3会引发PermissionError错误。因此,测试一次以查看它为您的Python版本引发了什么类型的异常是个好主意。 - Ecno92
我通常将EnvironmentError作为IOErrorOSErrorWindowsError的基类来捕获。 - Peter Wood

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接