2011-06-09 19 views
10

Me gustaría crear un directorio temporal único en Windows desde algún código C (no C++ o C#). Quiero hacer esto para poder poner algunos archivos temporales en el directorio y luego eliminarlos fácilmente cuando haya terminado (eliminando el directorio recursivamente).Creando un directorio temporal único de C puro en Windows

Estoy buscando esencialmente un equivalente de la función de mkdtemp de linux. Hay una respuesta de C# here, y las respuestas en this question sugieren usar Boost. Pero dado que estoy usando C, esas soluciones no funcionan para mí.

El mejor que he podido llegar a hasta el momento es el uso de GetTempFileName seguido por CreateDirectory, pero el problema no es que si te pido GetTempFileName para crear un nombre de archivo único, sino que también crea el archivo (que I no quiero, ya que quiero hacer un directorio en su lugar).

En relación con esto, hay GetTempPath, que devuelve la ubicación de la carpeta temporal del usuario del entorno de las variables - pero como yo quiero crear mi propio directorio que puedo eliminar de forma segura después, todavía tienen que crear un directorio en el interior cualquier ruta que devolvería.

Parece que si quiero un directorio único se cree, voy a tener que crear un archivo temporal, obtener el nombre, borrar, y luego crear un directorio con el mismo nombre - que suena muy desordenado . ¿Alguna otra idea?

+3

La idea en su párrafo final no funcionaría, estaría sujeta a condiciones de carrera. –

Respuesta

8

Puede usar lo que GetTempPath devuelve concatenado con un Guid para garantizar la exclusividad del directorio. Puede crear un Guid usando UuidCreate o CoCreateGuid Function.

Para eliminar recursivamente el directorio, hay un ejemplo aquí en C puro: How to remove directory recursively? basado en FindFirstFile, FindNextFile, DeleteFile y RemoveDirectory.

También hay SHFileOperation pero es más pesado y se basa en las funciones del shell de Windows, y las DLL de shell no siempre se desean, especialmente si está escribiendo código de servidor.

+0

Pensé en usar un GUID o UUID, pero no pude ver cómo convertirlo a una cadena. Investigar más me compró en ['StringFromGUID2'] (http://msdn.microsoft.com/en-us/library/ms683893 (v = VS.85) .aspx), lo que podría hacer el truco, siempre y cuando ganase ¿No genera caracteres que no pueden ir en nombres de archivo? Parece que solo generará cadenas hexagonales, lo que debería estar bien. –

+0

@Timothy: los formatos de guía estándar están bien para los nombres de archivo, pero de todos modos, como no necesita estos formatos guid, explícitamente no necesita StringFromGUIS2, ya que también puede generar el nombre de archivo "manualmente" usando una concatenación del 16 bytes escritos usando formato hexadecimal. –

3

Use GetTempPath luego CreateDirectory con un nombre aleatorio debajo de él, opcionalmente reintentando si CreateDirectory falla debido a que ya existe. Pero si la generación de su nombre es lo suficientemente buena, la probabilidad de una colisión con un nombre existente es mucho menor que la probabilidad de que un blackhat adivine su contraseña o incluso su clave privada, por lo que también podría ignorarla.

+1

Esto es esencialmente lo que 'mkdtemp' hace (incluido el intento, por supuesto). – andrewdski

2

Use _tempnamtmpnam_s para crear un nombre de archivo que no exista todavía, y luego use CreateDirectory para crear el directorio. Técnicamente, hay una condición de carrera si haces esto, ya que otro proceso podría potencialmente crear un archivo o directorio con ese nombre en el tiempo intermedio entre cuando generas el nombre del archivo y cuando creas el directorio, pero las probabilidades son bastante improbables. Para protegerse de eso, puede repetir hasta que tenga éxito.

Para eliminar recursivamente un árbol de directorios, puede usar SHFileOperation. Alternativamente, puede hacer el recorrido del directorio usted mismo con FindFirstFile/FindNextFile, DeleteFile, y RemoveDirectory.

Si desea eliminar el directorio automáticamente al salir, registre una función usando atexit. Esto solo funcionará para la terminación normal del programa (es decir, a través de la función exit o volviendo del main/WinMain). Esto no funcionará para la terminación anormal del programa (por ejemplo, a través del abort, una infracción de acceso, alguien más llamando al TerminateProcess, etc.).

Cuestiones relacionadas