+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+struct dirent {
+ ino_t d_ino; /* inode number */
+ off_t d_off; /* offset to the next dirent */
+ unsigned short int d_reclen; /* length of this record */
+ unsigned char d_type; /* type of file */
+ char d_name[256]; /* We must not include limits.h! */
+};
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \structd{dirent} per la lettura delle informazioni dei
+ file.}
+ \label{fig:file_dirent_struct}
+\end{figure}
+
+La presenza di ulteriori campi opzionali è segnalata dalla definizione di
+altrettante macro nella forma \code{\_DIRENT\_HAVE\_D\_XXX} dove \code{XXX} è
+il nome del relativo campo; nel nostro caso sono definite le macro
+\macro{\_DIRENT\_HAVE\_D\_TYPE}, \macro{\_DIRENT\_HAVE\_D\_OFF} e
+\macro{\_DIRENT\_HAVE\_D\_RECLEN}.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|l|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{DT\_UNKNOWN} & tipo sconosciuto. \\
+ \const{DT\_REG} & file normale. \\
+ \const{DT\_DIR} & directory. \\
+ \const{DT\_FIFO} & fifo. \\
+ \const{DT\_SOCK} & socket. \\
+ \const{DT\_CHR} & dispositivo a caratteri. \\
+ \const{DT\_BLK} & dispositivo a blocchi. \\
+ \hline
+ \end{tabular}
+ \caption{Costanti che indicano i vari tipi di file nel campo \var{d\_type}
+ della struttura \struct{dirent}.}
+ \label{tab:file_dtype_macro}
+\end{table}
+
+Per quanto riguarda il significato dei campi opzionali, il campo \var{d\_type}
+indica il tipo di file (fifo, directory, link simbolico, ecc.); i suoi
+possibili valori sono riportati in \tabref{tab:file_dtype_macro}; per la
+conversione da e verso l'analogo valore mantenuto dentro il campo
+\var{st\_mode} di \struct{stat} sono definite anche due macro di conversione
+\macro{IFTODT} e \macro{DTTOIF}:
+\begin{functions}
+ \funcdecl{int IFTODT(mode\_t MODE)} Converte il tipo di file dal formato di
+ \var{st\_mode} a quello di \var{d\_type}.
+
+ \funcdecl{mode\_t DTTOIF(int DTYPE)} Converte il tipo di file dal formato di
+ \var{d\_type} a quello di \var{st\_mode}.
+\end{functions}
+
+Il campo \var{d\_off} contiene invece la posizione della voce successiva della
+directory, mentre il campo \var{d\_reclen} la lunghezza totale della voce
+letta. Con questi due campi diventa possibile, determinando la posizione delle
+varie voci, spostarsi all'interno dello stream usando la funzione
+\func{seekdir},\footnote{sia questa funzione, che la corrispondente
+ \func{telldir}, sono estensioni prese da BSD, non previste dallo standard
+ POSIX.} il cui prototipo è:
+\begin{prototype}{dirent.h}{void seekdir(DIR *dir, off\_t offset)}
+ Cambia la posizione all'interno di un \textit{directory stream}.
+\end{prototype}
+
+La funzione non ritorna nulla e non segnala errori, è però necessario che il
+valore dell'argomento \param{offset} sia valido per lo stream \param{dir};
+esso pertanto deve essere stato ottenuto o dal valore di \var{d\_off} di
+\struct{dirent} o dal valore restituito dalla funzione \func{telldir}, che
+legge la posizione corrente; il prototipo di quest'ultima è:
+\begin{prototype}{dirent.h}{off\_t telldir(DIR *dir)}
+ Ritorna la posizione corrente in un \textit{directory stream}.
+
+ \bodydesc{La funzione restituisce la posizione corrente nello stream (un
+ numero positivo) in caso di successo, e -1 altrimenti, nel qual caso
+ \var{errno} assume solo il valore di \errval{EBADF}, corrispondente ad un
+ valore errrato per \param{dir}.}
+\end{prototype}
+
+La sola funzione di posizionamento nello stream prevista dallo standard POSIX
+è \funcd{rewinddir}, che riporta la posizione a quella iniziale; il suo
+prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h} \headdecl{dirent.h}
+
+ \funcdecl{void rewinddir(DIR *dir)}
+
+ Si posiziona all'inzio di un \textit{directory stream}.
+\end{functions}
+
+
+Una volta completate le operazioni si può chiudere il \textit{directory
+ stream} con la funzione \funcd{closedir}, il cui prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h} \headdecl{dirent.h}
+
+ \funcdecl{int closedir(DIR * dir)}
+
+ Chiude un \textit{directory stream}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 altrimenti, nel
+ qual caso \var{errno} assume il valore \errval{EBADF}.}
+\end{functions}
+
+A parte queste funzioni di base in BSD 4.3 è stata introdotta un'altra
+funzione che permette di eseguire una scansione completa (con tanto di ricerca
+ed ordinamento) del contenuto di una directory; la funzione è
+\funcd{scandir}\footnote{in Linux questa funzione è stata introdotta fin dalle
+ libc4.} ed il suo prototipo è:
+\begin{prototype}{dirent.h}{int scandir(const char *dir,
+ struct dirent ***namelist, int(*select)(const struct dirent *),
+ int(*compar)(const struct dirent **, const struct dirent **))}
+
+ Esegue una scansione di un \textit{directory stream}.
+
+ \bodydesc{La funzione restituisce in caso di successo il numero di voci
+ trovate, e -1 altrimenti.}
+\end{prototype}
+
+Al solito, per la presenza fra gli argomenti di due puntatori a funzione, il
+prototipo non è molto comprensibile; queste funzioni però sono quelle che
+controllano rispettivamente la selezione di una voce (\param{select}) e
+l'ordinamento di tutte le voci selezionate (\param{compar}).
+
+La funzione legge tutte le voci della directory indicata dall'argomento
+\param{dir}, passando ciascuna di esse come argomento alla funzione di
+\param{select}; se questa ritorna un valore diverso da zero la voce viene
+inserita in una struttura allocata dinamicamante con \func{malloc}, qualora si
+specifichi un valore \val{NULL} per \func{select} vengono selezionate tutte le
+voci. Tutte le voci selezionate vengono poi inserite un una lista (anch'essa
+allocata con \func{malloc}, che viene riordinata tramite \func{qsort} usando
+la funzione \param{compar} come criterio di ordinamento; alla fine l'indirizzo
+della lista ordinata è restituito nell'argomento \param{namelist}.
+
+Per l'ordinamento sono disponibili anche due funzioni predefinite,
+\funcd{alphasort} e \funcd{versionsort}, i cui prototipi sono:
+\begin{functions}
+ \headdecl{dirent.h}
+
+ \funcdecl{int alphasort(const void *a, const void *b)}
+
+ \funcdecl{int versionsort(const void *a, const void *b)}
+
+ Funzioni per l'ordinamento delle voci di \textit{directory stream}.
+
+ \bodydesc{Le funzioni restituiscono un valore minore, uguale o maggiore di
+ zero qualora il primo argomento sia rispettivamente minore, uguale o
+ maggiore del secondo.}
+\end{functions}
+
+
+La funzione \func{alphasort} deriva da BSD ed è presente in Linux fin dalle
+libc4\footnote{la versione delle libc4 e libc5 usa però come argomenti dei
+ puntatori a delle strutture \struct{dirent}; le glibc usano il prototipo
+ originario di BSD, mostrato anche nella definizione, che prevede puntatori a
+ \ctyp{void}.} e deve essere specificata come argomento \param{compare} per
+ottenere un ordinamento alfabetico (secondo il valore del campo \var{d\_name}
+delle varie voci). Le \acr{glibc} prevedono come estensione\footnote{le glibc,
+ a partire dalla versione 2.1, effettuano anche l'ordinamento alfabetico
+ tenendo conto delle varie localizzazioni, usando \func{strcoll} al posto di
+ \func{strcmp}.} anche \func{versionsort}, che ordina i nomi tenendo conto
+del numero di versione (cioè qualcosa per cui \file{file10} viene comunque
+dopo \func{file4}.)
+
+
+
+
+\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 filename è espresso in forma
+relativa, dove il ``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 filename, 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} (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}