I File Temporanei in Linguaggio C
- I file temporanei sono file creati per memorizzare dati intermedi durante l'esecuzione di un programma e non sono destinati a essere conservati a lungo termine.
- La funzione
tmpfile()crea un file temporaneo che viene eliminato automaticamente alla chiusura o alla terminazione del programma. - La funzione
tmpnam()genera un nome di file unico che può essere utilizzato per creare un file temporaneo in modo sicuro. - I file temporanei creati con
tmpnam()efopen()non vengono eliminati automaticamente, quindi è responsabilità del programmatore eliminarli quando non sono più necessari.
I File Temporanei
Le applicazioni e i programmi del mondo reale spesso necessitano di creare file temporanei per memorizzare dati intermedi durante l'esecuzione.
La caratteristica principale di questi file è che non sono destinati a essere conservati a lungo termine; vengono creati per un uso temporaneo e poi eliminati una volta che non sono più necessari e comunque prima della terminazione del programma.
Questa esigenza può sorgere in vari scenari, come ad esempio:
-
Quando si elaborano grandi quantità di dati che non possono essere tenuti interamente in memoria.
La memoria RAM di un computer è limitata, e per operazioni che coinvolgono dataset molto grandi, può essere necessario scrivere temporaneamente i dati su disco per evitare di esaurire la memoria.
-
Quando si eseguono operazioni che richiedono più fasi di elaborazione.
In questi casi, i file temporanei possono essere utilizzati per memorizzare i risultati intermedi tra le diverse fasi di elaborazione.
-
Quando si desidera isolare i dati temporanei dai dati permanenti.
Un esempio classico di file temporanei sono i file di swap utilizzati dai sistemi operativi per estendere la memoria virtuale. Così come i file intermedi generati dai compilatori, tra cui anche gcc, durante il processo di compilazione del codice sorgente in codice oggetto e infine in eseguibile.
Una volta che tali programmi terminano la loro esecuzione, i file temporanei vengono eliminati per liberare spazio su disco e mantenere il sistema pulito. Non vi è, infatti, alcun motivo per conservare questi file dopo che il programma ha completato il suo compito.
La libreria standard del linguaggio C fornisce delle funzionalità specifiche per la gestione dei file temporanei: le funzioni tmpfile() e tmpnam() che vedremo in dettaglio.
La funzione tmpfile
La funzione tmpfile() viene utilizzata per creare un file temporaneo che esiste fino a che non viene chiuso o fino alla terminazione del programma. Questa funzione apre un file temporaneo in modalità binaria di lettura e scrittura (ossia in modalità "wb+") e restituisce un puntatore a un oggetto di tipo FILE che rappresenta il file temporaneo. Essa è definita nel file di intestazione <stdio.h>.
La sua sintassi è la seguente:
#include <stdio.h>
FILE *tmpfile(void);
Essa può, ad esempio, essere utilizzata nel seguente modo:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *temp = tmpfile();
if (temp == NULL) {
printf("Errore nella creazione del file temporaneo.\n");
return EXIT_FAILURE;
}
// Utilizzo del file temporaneo
// Chiudere il file temporaneo
fclose(temp);
return EXIT_SUCCESS;
}
Da notare che in caso di fallimento, tmpfile() restituisce un puntatore nullo (NULL), quindi è buona pratica controllare il valore restituito prima di utilizzare il file temporaneo.
Inoltre, il file temporaneo creato da tmpfile() viene automaticamente eliminato dal sistema quando viene chiuso con fclose() o quando il programma termina, quindi non è necessario preoccuparsi di cancellarlo manualmente.
La funzione tmpfile() è particolarmente utile quando si ha bisogno di un file temporaneo per memorizzare dati intermedi senza dover gestire manualmente la creazione e la cancellazione del file sul filesystem. Tuttavia, essa presenta due problemi:
- Non consente di specificare il nome del file temporaneo, che viene generato automaticamente dal sistema operativo. Non solo, essa non fornisce alcun modo per conoscere il nome del file temporaneo creato.
- Non si può fare in modo che il file temporaneo persista dopo la chiusura o la terminazione del programma. Ad esempio, potrebbe sorgere l'esigenza in alcuni casi di voler mantenere il file temporaneo per un uso successivo. Questo non è possibile con
tmpfile(), poiché il file viene eliminato automaticamente.
Se queste due limitazioni sono problematiche, si potrebbe pensare, allora, di utilizzare la funzione fopen per creare un file temporaneo con un nome specifico. Tuttavia, questo approccio presenta dei rischi, in quanto potrebbe portare a conflitti di nomi con file esistenti o a problemi di sicurezza.
Infatti, se un file con lo stesso nome esiste già, fopen lo sovrascriverebbe senza preavviso, causando la perdita dei dati originali. Inoltre, un utente malintenzionato potrebbe creare un file con lo stesso nome in anticipo, portando a vulnerabilità di sicurezza.
Per questo motivo, è preferibile utilizzare metodi più sicuri per la creazione di file temporanei, come la funzione tmpnam() che vedremo adesso.
La funzione tmpnam
La funzione tmpnam(), sempre definita nel file di intestazione <stdio.h>, in realtà non crea un file temporaneo ne tantomeno lo apre. Essa genera semplicemente un nome di file unico che può essere utilizzato per creare un file temporaneo in modo sicuro.
In altre parole, tmpnam() fornisce un modo per ottenere un nome di file che è improbabile che entri in conflitto con altri file esistenti nel filesystem.
La sua sintassi è la seguente:
#include <stdio.h>
char *tmpnam(char *str);
La firma della funzione tmpnam è un po' strana: essa accetta come parametro un puntatore a una stringa di caratteri (char *str) e restituisce un puntatore a una stringa di caratteri. Il motivo è presto detto:
- Se il parametro in ingresso
strèNULL, la funzionetmpnam()utilizza un buffer interno per memorizzare il nome del file temporaneo generato e restituisce un puntatore a questo buffer. - Se il parametro in ingresso
strnon èNULL, la funzionetmpnam()scrive il nome del file temporaneo generato nel buffer fornito dall'utente (ossia instr) e restituisce un puntatore a questo buffer.
In altre parole, se passiamo come argomento un puntatore NULL, la funzione utilizza un buffer interno su cui scrivere il nome del file temporaneo generato. Questo buffer viene, poi, restituito come valore di ritorno della funzione:
char *nome_file = tmpnam(NULL);
Questo approccio è comodo, ma ha lo svantaggio che il buffer interno viene sovrascritto ad ogni chiamata successiva a tmpnam(), quindi se si desidera conservare il nome del file temporaneo generato, oppure se si prevede di chiamare tmpnam() più volte, è meglio fornire un proprio buffer:
char buffer[L_tmpnam];
char *nome_file = tmpnam(buffer);
Da notare che L_tmpnam è una macro definita in <stdio.h> che specifica la lunghezza massima del nome del file temporaneo generato da tmpnam(). Utilizzando questa macro, possiamo assicurarci che il buffer fornito sia sufficientemente grande per contenere il nome del file temporaneo.
Riprendiamo l'esempio di sopra e vediamo come utilizzare tmpnam() per creare un file temporaneo in modo sicuro:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
// Genera il nome del file temporaneo
char nome_file[L_tmpnam];
if (tmpnam(nome_file) == NULL) {
printf("Errore nella generazione del nome del file temporaneo.\n");
return EXIT_FAILURE;
}
// Crea e apre il file temporaneo
FILE *temp = fopen(nome_file, "wb+");
if (temp == NULL) {
printf("Errore nella creazione del file temporaneo.\n");
return EXIT_FAILURE;
}
// Utilizzo del file temporaneo
// Chiude il file temporaneo
fclose(temp);
// Elimina il file temporaneo
remove(nome_file);
return EXIT_SUCCESS;
}
In questo esempio, utilizziamo tmpnam() per generare un nome di file temporaneo unico e sicuro, quindi utilizziamo fopen() per creare e aprire il file temporaneo. Dopo aver utilizzato il file, lo chiudiamo con fclose() e lo eliminiamo manualmente con la funzione remove(). Non abbiamo ancora studiato la funzione remove(), ma essa è definita in <stdio.h> e viene utilizzata per eliminare un file dal filesystem. La vedremo in dettaglio in una lezione successiva.
Da notare che, a differenza di tmpfile(), il file temporaneo creato con tmpnam() e fopen() non viene eliminato automaticamente alla chiusura o alla terminazione del programma, quindi è nostra responsabilità eliminarlo quando non è più necessario.
Esiste, infine, un'altro avvertimento riguardo l'uso di tmpnam(): esiste un numero massimo di volte in cui è possibile chiamare tmpnam() per generare nomi di file unici. Tale numero è definito dalla macro TMP_MAX, anch'essa definita in <stdio.h>. Se si supera questo limite, tmpnam() inizierà a restituire puntatori a NULL, indicando che non è più possibile generare nomi di file unici. Tuttavia, nella maggior parte delle applicazioni pratiche, questo limite non viene quasi mai raggiunto. Ad esempio, in un sistema tipico Linux, TMP_MAX è spesso definito come 238328, il che significa che è possibile generare fino a 238328 nomi di file unici prima di esaurire le possibilità.