2011-06-09 19 views
10

Vorrei creare una directory temporanea univoca in Windows da un codice C (non C++ o C#). Voglio fare questo in modo che possa mettere alcuni file temporanei nella directory, e poi cancellarli tutti facilmente quando ho finito di scrivere (rimuovendo la directory in modo ricorsivo).Creazione di una directory temporanea univoca da C pura in windows

Sono essenzialmente alla ricerca di un equivalente della funzione linux mkdtemp . C'è una risposta C# here, e le risposte su this question suggeriscono di usare Boost. Ma dal momento che sto usando C, quelle soluzioni non funzionano per me .

Il meglio che ho potuto venire in mente finora è quello di utilizzare GetTempFileName seguito da CreateDirectory, ma il problema non è che se chiedo GetTempFileName per creare un nome di file univoco, lo farà anche creare il file (che io non desidero I , poiché voglio creare una directory).

relazione a ciò, c'è GetTempPath, che restituisce la posizione della cartella Temp dell'utente dall'ambiente variabili - ma dal momento che voglio creare la mia propria directory che posso tranquillamente cancellare più tardi, ho ancora bisogno di creare una directory all'interno qualsiasi percorso che restituirebbe.

Sembra che se voglio una directory unica per creare, dovrò creare un file temporaneo, ottenere il nome, eliminarlo, e quindi creare una directory con lo stesso nome - che suona molto disordinato . Qualche altra idea?

+3

L'idea nel tuo ultimo paragrafo non funzionerebbe, sarebbe soggetta a condizioni di gara. –

risposta

8

È possibile utilizzare i resi GetTempPath concatenati con un Guid per garantire l'univocità della directory. È possibile creare una guida utilizzando UuidCreate o CoCreateGuid Function.

Per eliminare in modo ricorsivo la directory, c'è un esempio qui in puro C: How to remove directory recursively? basato su FindFirstFile, FindNextFile, DeleteFile e RemoveDirectory.

C'è anche SHFileOperation ma è più pesante e si basa sulle funzioni della shell di Windows e le DLL della shell non sono sempre ricercate, specialmente se si sta scrivendo il codice del server.

+0

Ho pensato di utilizzare un GUID o UUID, ma non sono riuscito a vedere come convertire in una stringa. Ulteriori scavi mi hanno comprato in ['StringFromGUID2'] (http://msdn.microsoft.com/en-us/library/ms683893 (v = VS.85) .aspx), che potrebbe fare il trucco, a patto che vinca generare personaggi che non possono essere inseriti nei nomi dei file? Sembra che genererà solo stringhe esadecimali, che dovrebbero andare bene. –

+0

@Timothy - i formati standard guid vanno bene per i nomi dei file, ma comunque, dato che non hai bisogno di questi formati guid, non hai bisogno di StringFromGUIS2, dato che puoi anche generare il nome del file "manualmente" usando una concatenazione del 16 byte scritti utilizzando il formato esadecimale. –

3

Utilizzare GetTempPath quindi CreateDirectory con un nome casuale sotto di esso, eventualmente riprovare se CreateDirectory non riesce a causa di esso già esistente. Ma se la generazione del tuo nome è abbastanza buona, la probabilità di una collisione con un nome esistente è molto più piccola della probabilità che un blackhat indovini la tua password o persino la tua chiave privata, quindi potresti anche ignorarla.

+1

Questo è essenzialmente ciò che 'mkdtemp' fa (incluso il tentativo, ovviamente). – andrewdski

2

Utilizzare _tempnamtmpnam_s per creare un nome file che non esiste ancora e quindi utilizzare CreateDirectory per creare la directory. C'è tecnicamente una condizione di competizione se lo fai, in quanto un altro processo potrebbe potenzialmente creare un file o una directory con quel nome nel tempo tra quando generi il nome file e quando crei la directory, ma le probabilità sono piuttosto improbabili. Per proteggerti, puoi eseguire il loop finché non ci riesci.

Per la rimozione ricorsiva di un albero di directory, è possibile utilizzare SHFileOperation. In alternativa, è possibile eseguire personalmente la directory traversata con FindFirstFile/FindNextFile, DeleteFile e RemoveDirectory.

Se si desidera rimuovere automaticamente la directory all'uscita, registrare una funzione utilizzando atexit. Ciò funzionerà solo per la normale chiusura del programma (ad es. Tramite la funzione exit o tramite il ritorno da main/WinMain). Ciò non funzionerà per la terminazione anomala del programma (ad esempio tramite abort, una violazione di accesso, qualcun altro che chiama TerminateProcess, ecc.).