Deseo escribir en un archivo en función de si ese archivo ya existe o no, solo escribiendo si aún no existe (en la práctica, deseo seguir probando archivos hasta encontrar uno que no existe).
El siguiente código muestra una forma en que un atacante potencial podría insertar un enlace simbólico, como se sugiere en esta publicación, entre una prueba para el archivo y el archivo que se está escribiendo. Si el código se ejecuta con permisos suficientemente altos, esto podría sobrescribir un archivo arbitrario.
¿Hay alguna forma de solucionar 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')
Respuestas:
Editar : Vea también la respuesta de Dave Jones : desde Python 3.3, puede usar la
x
banderaopen()
para proporcionar esta función.Respuesta original a continuación
Sí, pero sin usar la
open()
llamada estándar de Python . Deberá usaros.open()
en su lugar, lo que le permite especificar indicadores en el código C subyacente.En particular, desea utilizar
O_CREAT | O_EXCL
. Desde la página de manual deopen(2)
underO_EXCL
en mi sistema Unix:Así que no es perfecto, pero AFAIK es lo más cerca que puedes estar de evitar esta condición de carrera.
Editar: las otras reglas de uso en
os.open()
lugar deopen()
todavía se aplican. En particular, si desea utilizar el descriptor de archivo devuelto para leer o escribir, también necesitará uno de los indicadoresO_RDONLY
,O_WRONLY
oO_RDWR
.Todas las
O_*
banderas están en elos
módulo de Python , por lo que necesitaráimport os
usar,os.O_CREAT
etc.Ejemplo:
fuente
Como referencia, Python 3.3 implementa un nuevo
'x'
modo en laopen()
función para cubrir este caso de uso (solo crear, fallar si el archivo existe). Tenga en cuenta que el'x'
modo se especifica por sí solo. El uso de'wx'
resultados en aValueError
como'w'
es redundante (lo único que puede hacer si la llamada tiene éxito es escribir en el archivo de todos modos; no puede haber existido si la llamada tiene éxito):Para Python 3.2 y versiones anteriores (incluido Python 2.x), consulte la respuesta aceptada .
fuente
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 creará fácilmente un ARCHIVO si no existe uno.
fuente
if
declaración, este código borrará el archivo.