当前位置: 首页 > 面试题库 >

仅当与python不存在时才安全创建文件

井礼骞
2023-03-14
问题内容

我希望根据该文件是否已经存在来写一个文件,仅在不存在的情况下才写(实际上,我希望继续尝试文件,直到找到一个不存在的文件为止)。

下面的代码显示在其中一个潜在的攻击者可以插入一个符号,作为建议的方式这篇文章中该文件的测试和写入的文件之间。如果代码以足够高的权限运行,则可能会覆盖任意文件。

有什么办法解决这个问题?

import os
import errno

file_to_be_attacked = 'important_file'

with open(file_to_be_attacked, 'w') as f:
    f.write('Some important content!\n')

test_file = 'testfile'

try:
    with open(test_file) as f: pass
except IOError, e:

    # symlink created here
    os.symlink(file_to_be_attacked, test_file)

    if e.errno != errno.ENOENT:
        raise
    else:
        with open(test_file, 'w') as f:
            f.write('Hello, kthxbye!\n')

问题答案:

编辑 :另请参见DaveJones的回答:从Python3.3开始,您可以使用该x标志open()来提供此功能。

作为参考,Python 3.3'x'open()函数中实现了一种新模式来涵盖此用例(仅创建,如果文件存在则失败)。请注意,'x'模式是单独指定的。使用'wx'结果中的ValueErroras'w'是多余的(无论如何,如果调用成功,您唯一可以做的就是将其写入文件;如果调用成功,它就不存在):

>>> f1 = open('new_binary_file', 'xb')
>>> f2 = open('new_text_file', 'x')

下面的原始答案

是的,但不使用Python的标准open()调用。您需要使用os.open()代替,它允许您为基础C代码指定标志。

特别是您要使用O_CREAT | O_EXCL。从该名男子页open(2)O_EXCL我的Unix系统:

确保此调用创建了文件:如果将此标志与一起指定O_CREAT,并且路径名已经存在,open()则将失败。O_EXCL如果O_CREAT未指定,则行为不确定。

当指定这两个标志时,将不遵循符号链接:如果pathname是符号链接,则open()无论符号链接指向何处都将失败。

O_EXCL
仅当在内核2.6或更高版本上使用NFSv3或更高版本时,NFS才支持该功能。在O_EXCL不提供NFS支持的环境中,依赖它执行锁定任务的程序将包含竞争条件。

因此,这并不完美,但AFAIK是避免这种情况的最接近的方法。

编辑:使用os.open()而不是其他规则open()仍然适用。特别是,如果你想使用返回的文件描述符进行读取或写入,你需要的一个O_RDONLYO_WRONLYO_RDWR标志以及。

所有O_*标志都在Python的os模块中,因此您需要import os使用os.O_CREAT等。

例:

import os
import errno

flags = os.O_CREAT | os.O_EXCL | os.O_WRONLY

try:
    file_handle = os.open('filename', flags)
except OSError as e:
    if e.errno == errno.EEXIST:  # Failed as the file already exists.
        pass
    else:  # Something unexpected went wrong so reraise the exception.
        raise
else:  # No exception, so the file must have been created successfully.
    with os.fdopen(file_handle, 'w') as file_obj:
        # Using `os.fdopen` converts the handle to an object that acts like a
        # regular Python file object, and the `with` context manager means the
        # file will be automatically closed when we're done with it.
        file_obj.write("Look, ma, I'm writing to a new file!")


 类似资料:
  • 我试图实现的很简单。只有当数据库不存在时,我才需要在数据库中创建一个用户条目。 应用程序流程: 使用Firebase身份验证(获取UID)创建用户 客户端代码(创建操作): firestore规则: 附加信息: 正如您可能已经知道的那样,代码不起作用。每次我运行客户端代码时,当前用户都会被一个新文档完全替换。但是,如果我从规则中删除以下行,一切都会正常工作: 但现在问题来了,如何保护用户文档中的数

  • 问题内容: 我有2张桌子- : 第二张桌子- : 我只需要选择未取消的预订(在此示例中仅为ID 3)。我可以轻松地选择带有简单条件的已取消,但由于未在此处取消工作,因此我在努力避免未取消。 问题答案: 要么: 第一个版本更直观,但是我认为第二个版本通常可以获得更好的性能(假设您在联接中使用的列上有索引)。 第二个版本有效,因为返回第一个表中所有行的一行。当条件成功,这些行会包括从第二表中的列,就像

  • 问题内容: 我需要将以下行添加到配置文件的末尾: 到一个名为 我正在寻找用于执行此操作的方法,但无法解决。 如果该行尚不存在,我将如何插入? 问题答案: 保持简单:) grep + echo 应该足够了: 安静 整行匹配 模式是一个普通的字符串 https://linux.die.net/man/1/grep 编辑:合并@cerin和@ thijs-wouters建议 。

  • 基于这个类似的问题,我想要一种性能最好的方法来处理这个场景。 不幸的是,IF不存在,并且EXISTS不能用于匹配或查找唯一节点。 null

  • 我目前正在连接这样的名字和姓氏(使用PostgreSQL): 我在这里遇到的问题是,我的客户只输入了一个名字(即“罗纳尔多”)。上面的查询将返回“罗纳尔多”,这将不匹配。 我可以使用我的服务器端语言来检查尾随空间,但是如果我的数据库中的某个地方有一个客户不小心输入了尾随空间(即“哈利波特”),那么我也不会匹配那个。 我正在寻找返回“罗纳尔多”、“约翰·史密斯”和“哈利·波特”的SQL。所以基本上,

  • 问题内容: 仅在不存在视图的情况下如何创建视图。如果确实存在,我想删除视图并重新定义它。我也不要警告或错误。 问题答案: 您将自己踢: 详细信息在这里。;-)