+Quest'ultima si limita (\texttt{\small 23}) a chiamare \func{stat} sul file
+indicato dalla directory entry passata come argomento (il cui nome è appunto
+\var{direntry->d\_name}), memorizzando in una opportuna struttura \var{data} i
+dati ad esso relativi, per poi provvedere (\texttt{\small 24}) a stampare il
+nome del file e la dimensione riportata in \var{data}.
+
+Dato che la funzione verrà chiamata all'interno di \func{DirScan} per ogni
+voce presente questo è sufficiente a stampare la lista completa dei file e
+delle relative dimensioni. Si noti infine come si restituisca sempre 0 come
+valore di ritorno per indicare una esecuzione senza errori.
+
+\begin{figure}[!htb]
+ \footnotesize
+ \begin{lstlisting}{}
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h> /* directory */
+#include <stdlib.h> /* C standard library */
+#include <unistd.h>
+
+/*
+ * Function DirScan:
+ *
+ * Input: the directory name and a computation function
+ * Return: 0 if OK, -1 on errors
+ */
+int DirScan(char * dirname, int(*compute)(struct dirent *))
+{
+ DIR * dir;
+ struct dirent *direntry;
+
+ if ( (dir = opendir(dirname)) == NULL) { /* oper directory */
+ printf("Opening %s\n", dirname); /* on error print messages */
+ perror("Cannot open directory"); /* and then return */
+ return -1;
+ }
+ fd = dirfd(dir); /* get file descriptor */
+ fchdir(fd); /* change directory */
+ /* loop on directory entries */
+ while ( (direntry = readdir(dir)) != NULL) { /* read entry */
+ if (compute(direntry)) { /* execute function on it */
+ return -1; /* on error return */
+ }
+ }
+ closedir(dir);
+ return 0;
+}
+
+ \end{lstlisting}
+ \caption{Codice della routine di scansione di una directory contenuta nel
+ file \file{DirScan.c}.}
+ \label{fig:file_dirscan}
+\end{figure}
+
+Tutto il grosso del lavoro è svolto dalla funzione \func{DirScan}, riportata
+in \figref{fig:file_dirscan}. La funzione è volutamente generica e permette di
+eseguire una funzione, passata come secondo argomento, su tutte le voci di una
+directory. La funzione inizia con l'aprire (\texttt{\small 19--23}) uno
+stream sulla directory passata come primo argomento, stampando un messaggio in
+caso di errore.
+
+Il passo successivo (\texttt{\small 24--25}) è cambiare directory di lavoro
+(vedi \secref{sec:file_work_dir}), usando in sequenza le funzione \func{dirfd}
+e \func{fchdir} (in realtà si sarebbe potuto usare direttamente \func{chdir}
+su \var{dirname}), in modo che durante il successivo ciclo (\texttt{\small
+ 27--31}) sulle singole voci dello stream ci si trovi all'interno della
+directory.\footnote{questo è essenziale al funzionamento della funzione
+ \code{do\_ls} (e ad ogni funzione che debba usare il campo \var{d\_name}, in
+ quanto i nomi dei file memorizzati all'interno di una struttura
+ \struct{dirent} sono sempre relativi alla directory in questione, e senza
+ questo posizionamento non si sarebbe potuto usare \func{stat} per ottenere
+ le dimensioni.}
+
+Avendo usato lo stratagemma di fare eseguire tutte le manipolazioni necessarie
+alla funzione passata come secondo argomento, il ciclo di scansione della
+directory è molto semplice; si legge una voce alla volta (\texttt{\small 27})
+all'interno di una istruzione di \code{while} e fintanto che si riceve una
+voce valida (cioè un puntatore diverso da \val{NULL}) si esegue
+(\texttt{\small 27}) la funzione di elaborazione \var{compare} (che nel nostro
+caso sarà \code{do\_ls}), ritornando con un codice di errore (\texttt{\small
+ 28}) qualora questa presenti una anomalia (identificata da un codice di
+ritorno negativo).
+
+Una volta terminato il ciclo la funzione si conclude con la chiusura
+(\texttt{\small 32}) dello stream\footnote{nel nostro caso, uscendo subito
+ dopo la chiamata, questo non servirebbe, in generale però l'operazione è
+ necessaria, dato che la funzione può essere invocata molte volte all'interno
+ dello stesso processo, per cui non chiudere gli stream comporterebbe un
+ consumo progressivo di risorse, con conseguente rischio di esaurimento delle
+ stesse} e la restituzione (\texttt{\small 33}) del codice di operazioni
+concluse con successo.
+
+
+\subsection{La directory di lavoro}
+\label{sec:file_work_dir}
+
+A ciascun processo è associata una directory nel filesystem che è chiamata
+directory corrente o directory di lavoro (\textit{current working directory})
+che è quella a cui si fa riferimento quando un pathname è espresso in forma
+relativa, dove il ``\textsl{relativa}'' fa riferimento appunto a questa
+directory.
+
+Quando un utente effettua il login, questa directory viene impostata alla
+\textit{home directory} del suo account. Il comando \cmd{cd} della shell
+consente di cambiarla a piacere, spostandosi da una directory ad un'altra, il
+comando \cmd{pwd} la stampa sul terminale. Siccome la directory corrente
+resta la stessa quando viene creato un processo figlio (vedi
+\secref{sec:proc_fork}), la directory corrente della shell diventa anche la
+directory corrente di qualunque comando da essa lanciato.
+
+In genere il kernel tiene traccia per ciascun processo dell'inode\index{inode}
+della directory di lavoro corrente, per ottenere il pathname occorre usare una
+apposita funzione di libreria, \funcd{getcwd}, il cui prototipo è:
+\begin{prototype}{unistd.h}{char *getcwd(char *buffer, size\_t size)}
+ Legge il pathname della directory di lavoro corrente.
+
+ \bodydesc{La funzione restituisce il puntatore \param{buffer} se riesce,
+ \val{NULL} se fallisce, in quest'ultimo caso la variabile
+ \var{errno} è impostata con i seguenti codici di errore:
+ \begin{errlist}
+ \item[\errcode{EINVAL}] L'argomento \param{size} è zero e \param{buffer} non
+ è nullo.
+ \item[\errcode{ERANGE}] L'argomento \param{size} è più piccolo della
+ lunghezza del pathname.
+ \item[\errcode{EACCES}] Manca il permesso di lettura o di ricerca su uno dei
+ componenti del pathname (cioè su una delle directory superiori alla
+ corrente).
+ \end{errlist}}
+\end{prototype}
+
+La funzione restituisce il pathname completo della directory di lavoro
+corrente nella stringa puntata da \param{buffer}, che deve essere
+precedentemente allocata, per una dimensione massima di \param{size}. Il
+buffer deve essere sufficientemente lungo da poter contenere il pathname
+completo più lo zero di terminazione della stringa. Qualora esso ecceda le
+dimensioni specificate con \param{size} la funzione restituisce un errore.
+
+Si può anche specificare un puntatore nullo come
+\param{buffer},\footnote{questa è un'estensione allo standard POSIX.1,
+ supportata da Linux.} nel qual caso la stringa sarà allocata automaticamente
+per una dimensione pari a \param{size} qualora questa sia diversa da zero, o
+della lunghezza esatta del pathname altrimenti. In questo caso ci si deve
+ricordare di disallocare la stringa una volta cessato il suo utilizzo.
+
+Di questa funzione esiste una versione \code{char *getwd(char *buffer)}
+fatta per compatibilità all'indietro con BSD, che non consente di specificare
+la dimensione del buffer; esso deve essere allocato in precedenza ed avere una
+dimensione superiore a \const{PATH\_MAX} (di solito 256 byte, vedi
+\secref{sec:sys_limits}); il problema è che in Linux non esiste una dimensione
+superiore per un pathname, per cui non è detto che il buffer sia sufficiente a
+contenere il nome del file, e questa è la ragione principale per cui questa
+funzione è deprecata.
+
+Una seconda funzione simile è \code{char *get\_current\_dir\_name(void)} che è
+sostanzialmente equivalente ad una \code{getcwd(NULL, 0)}, con la sola
+differenza che essa ritorna il valore della variabile di ambiente \val{PWD},
+che essendo costruita dalla shell può contenere un pathname comprendente anche
+dei link simbolici. Usando \func{getcwd} infatti, essendo il pathname ricavato
+risalendo all'indietro l'albero della directory, si perderebbe traccia di ogni
+passaggio attraverso eventuali link simbolici.
+
+Per cambiare la directory di lavoro corrente si può usare la funzione
+\funcd{chdir} (equivalente del comando di shell \cmd{cd}) il cui nome sta
+appunto per \textit{change directory}, il suo prototipo è:
+\begin{prototype}{unistd.h}{int chdir(const char *pathname)}
+ Cambia la directory di lavoro corrente in \param{pathname}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 per un errore,
+ nel qual caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\errcode{ENOTDIR}] Non si è specificata una directory.
+ \item[\errcode{EACCES}] Manca il permesso di ricerca su uno dei componenti
+ di \param{path}.
+ \end{errlist}
+ ed inoltre \errval{EFAULT}, \errval{ENAMETOOLONG}, \errval{ENOENT},
+ \errval{ENOMEM}, \errval{ELOOP} e \errval{EIO}.}
+\end{prototype}
+\noindent ed ovviamente \param{pathname} deve indicare una directory per la
+quale si hanno i permessi di accesso.
+
+Dato che anche le directory sono file, è possibile riferirsi ad esse anche
+tramite il file descriptor, e non solo tramite il pathname, per fare questo si
+usa \funcd{fchdir}, il cui prototipo è:
+\begin{prototype}{unistd.h}{int fchdir(int fd)}
+ Identica a \func{chdir}, ma usa il file descriptor \param{fd} invece del
+ pathname.
+
+ \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+ errore, in caso di errore \var{errno} assumerà i valori \errval{EBADF} o
+ \errval{EACCES}.}
+\end{prototype}
+\noindent anche in questo caso \param{fd} deve essere un file descriptor
+valido che fa riferimento ad una directory. Inoltre l'unico errore di accesso
+possibile (tutti gli altri sarebbero occorsi all'apertura di \param{fd}), è
+quello in cui il processo non ha il permesso di accesso alla directory
+specificata da \param{fd}.
+
+
+
+\subsection{I file temporanei}
+\label{sec:file_temp_file}
+
+In molte occasioni è utile poter creare dei file temporanei; benché la cosa
+sembri semplice, in realtà il problema è più sottile di quanto non appaia a
+prima vista. Infatti anche se sembrerebbe banale generare un nome a caso e
+creare il file dopo aver controllato che questo non esista, nel momento fra il
+controllo e la creazione si ha giusto lo spazio per una possibile \textit{race
+ condition}\index{race condition} (si ricordi quanto visto in
+\secref{sec:proc_race_cond}).
+
+Le \acr{glibc} provvedono varie funzioni per generare nomi di file temporanei,
+di cui si abbia certezza di unicità (al momento della generazione); la prima
+di queste funzioni è \funcd{tmpnam} il cui prototipo è:
+\begin{prototype}{stdio.h}{char *tmpnam(char *string)}
+ Restituisce il puntatore ad una stringa contente un nome di file valido e
+ non esistente al momento dell'invocazione.
+
+ \bodydesc{La funzione ritorna il puntatore alla stringa con il nome o
+ \val{NULL} in caso di fallimento. Non sono definiti errori.}
+\end{prototype}
+\noindent se si è passato un puntatore \param{string} non nullo questo deve
+essere di dimensione \const{L\_tmpnam} (costante definita in \file{stdio.h},
+come \const{P\_tmpdir} e \const{TMP\_MAX}) ed il nome generato vi verrà
+copiato automaticamente; altrimenti il nome sarà generato in un buffer statico
+interno che verrà sovrascritto ad una chiamata successiva. Successive
+invocazioni della funzione continueranno a restituire nomi unici fino ad un
+massimo di \const{TMP\_MAX} volte. Al nome viene automaticamente aggiunto come
+prefisso la directory specificata da \const{P\_tmpdir}.
+
+Di questa funzione esiste una versione rientrante, \func{tmpnam\_r}, che non
+fa nulla quando si passa \val{NULL} come parametro. Una funzione simile,
+\funcd{tempnam}, permette di specificare un prefisso per il file
+esplicitamente, il suo prototipo è:
+\begin{prototype}{stdio.h}{char *tempnam(const char *dir, const char *pfx)}
+ Restituisce il puntatore ad una stringa contente un nome di file valido e
+ non esistente al momento dell'invocazione.
+
+ \bodydesc{La funzione ritorna il puntatore alla stringa con il nome o
+ \val{NULL} in caso di fallimento, \var{errno} viene impostata a
+ \errval{ENOMEM} qualora fallisca l'allocazione della stringa.}
+\end{prototype}