Desejo gravar em um arquivo com base no fato de esse arquivo já existir ou não, somente gravando se ele ainda não existir (na prática, desejo continuar tentando arquivos até encontrar um que não exista).
O código a seguir mostra uma maneira pela qual um invasor em potencial pode inserir um link simbólico, conforme sugerido nesta postagem , entre um teste para o arquivo e o arquivo que está sendo escrito. Se o código for executado com permissões altas o suficiente, isso pode substituir um arquivo arbitrário.
Existe alguma maneira de resolver este problema?
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')
Respostas:
Editar : Veja também a resposta de Dave Jones : no Python 3.3, você pode usar o
x
sinalizadoropen()
para fornecer essa função.Resposta original abaixo
Sim, mas não usando a
open()
chamada padrão do Python . Emos.open()
vez disso, você precisará usar , o que permite especificar sinalizadores para o código C subjacente.Em particular, você deseja usar
O_CREAT | O_EXCL
. A partir da página homem poropen(2)
debaixoO_EXCL
no meu sistema Unix:Portanto, não é perfeito, mas AFAIK é o mais perto que você pode chegar de evitar essa condição de corrida.
Editar: as outras regras de uso em
os.open()
vez deopen()
ainda se aplicam. Em particular, se você quiser usar o descritor de arquivo retornado para ler ou escrever, você vai precisar de um dosO_RDONLY
,O_WRONLY
ouO_RDWR
bandeiras também.Todos os
O_*
sinalizadores estão noos
módulo do Python , então você precisaráimport os
usaros.O_CREAT
etc.Exemplo:
fonte
Para referência, Python 3.3 implementa um novo
'x'
modo naopen()
função para cobrir este caso de uso (criar apenas, falhar se o arquivo existir). Observe que o'x'
modo é especificado por conta própria. Usar'wx'
resultados em aValueError
como o'w'
é redundante (a única coisa que você pode fazer se a chamada for bem-sucedida é gravar no arquivo; ele não pode ter existido se a chamada for bem-sucedida):Para Python 3.2 e inferior (incluindo Python 2.x), consulte a resposta aceita .
fonte
Python 3.2 (r32:88445, Feb 20 2011, 21:30:00)
[MSC v.1500 64 bit (AMD64)] on win32
>>> open("c:/temp/foo.csv","wx")
ValueError: invalid mode: 'wx'
ValueError: must have exactly one of create/read/write/append mode
Este código criará facilmente um ARQUIVO se não houver um.
fonte
if
instrução, esse código apagará o arquivo.