+Un caso comune che si può avere con i link simbolici è la creazione dei
+cosiddetti \textit{loop}. La situazione è illustrata in
+\figref{fig:file_link_loop}, che riporta la struttura della directory
+\file{/boot}. Come si vede si è creato al suo interno un link simbolico che
+punta di nuovo a \file{/boot}.\footnote{il loop mostrato in
+ \figref{fig:file_link_loop} è un usato per poter permettere a \cmd{grub} (un
+ bootloader in grado di leggere direttamente da vari filesystem il file da
+ lanciare come sistema operativo) di vedere i file contenuti nella directory
+ \file{/boot} con lo stesso pathname con cui verrebbero visti dal sistema
+ operativo, anche se essi si trovano, come accade spesso, su una partizione
+ separata (che \cmd{grub}, all'avvio, vede come radice).}
+
+Questo può causare problemi per tutti quei programmi che effettuano la
+scansione di una directory senza tener conto dei link simbolici, ad esempio se
+lanciassimo un comando del tipo \code{grep -r linux *}, il loop nella
+directory porterebbe il comando ad esaminare \file{/boot}, \file{/boot/boot},
+\file{/boot/boot/boot} e così via.
+
+Per questo motivo il kernel e le librerie prevedono che nella risoluzione di
+un pathname possano essere seguiti un numero limitato di link simbolici, il
+cui valore limite è specificato dalla costante \const{MAXSYMLINKS}. Qualora
+questo limite venga superato viene generato un errore ed \var{errno} viene
+impostata al valore \errcode{ELOOP}.
+
+Un punto da tenere sempre presente è che, come abbiamo accennato, un link
+simbolico può fare riferimento anche ad un file che non esiste; ad esempio
+possiamo creare un file temporaneo nella nostra directory con un link del
+tipo:
+\begin{verbatim}
+$ ln -s /tmp/tmp_file temporaneo
+\end{verbatim}%$
+anche se \file{/tmp/tmp\_file} non esiste. Questo può generare confusione, in
+quanto aprendo in scrittura \file{temporaneo} verrà creato
+\file{/tmp/tmp\_file} e scritto; ma accedendo in sola lettura a
+\file{temporaneo}, ad esempio con \cmd{cat}, otterremmo:
+\begin{verbatim}
+$ cat temporaneo
+cat: temporaneo: No such file or directory
+\end{verbatim}%$
+con un errore che può sembrare sbagliato, dato che un'ispezione con \cmd{ls}
+ci mostrerebbe invece l'esistenza di \file{temporaneo}.
+
+
+\subsection{La creazione e la cancellazione delle directory}
+\label{sec:file_dir_creat_rem}
+
+Benché in sostanza le directory non siano altro che dei file contenenti
+elenchi di nomi ed inode, non è possibile trattarle come file ordinari e
+devono essere create direttamente dal kernel attraverso una opportuna system
+call.\footnote{questo permette anche, attraverso l'uso del VFS, l'utilizzo di
+ diversi formati per la gestione dei suddetti elenchi.} La funzione usata
+per creare una directory è \funcd{mkdir}, ed il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/stat.h}
+ \headdecl{sys/types.h}
+ \funcdecl{int mkdir(const char *dirname, mode\_t mode)}
+
+ Crea una nuova directory.
+
+ \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+ errore, nel qual caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\errcode{EEXIST}] Un file (o una directory) con quel nome esiste di
+ già.
+ \item[\errcode{EACCES}]
+ Non c'è il permesso di scrittura per la directory in cui si vuole inserire
+ la nuova directory.
+ \item[\errcode{EMLINK}] La directory in cui si vuole creare la nuova
+ directory contiene troppi file. Sotto Linux questo normalmente non avviene
+ perché il filesystem standard consente la creazione di un numero di file
+ maggiore di quelli che possono essere contenuti nel disco, ma potendo
+ avere a che fare anche con filesystem di altri sistemi questo errore può
+ presentarsi.
+ \item[\errcode{ENOSPC}] Non c'è abbastanza spazio sul file system per creare
+ la nuova directory o si è esaurita la quota disco dell'utente.
+ \end{errlist}
+ ed inoltre anche \errval{EPERM}, \errval{EFAULT}, \errval{ENAMETOOLONG},
+ \errval{ENOENT}, \errval{ENOTDIR}, \errval{ENOMEM}, \errval{ELOOP},
+ \errval{EROFS}.}
+\end{functions}
+
+La funzione crea una nuova directory vuota, che contiene cioè solo le due voci
+standard (\file{.} e \file{..}), con il nome indicato dall'argomento
+\param{dirname}. Il nome può essere indicato sia come pathname assoluto che
+relativo.
+
+I permessi di accesso alla directory (vedi \secref{sec:file_access_control})
+sono specificati da \param{mode}, i cui possibili valori sono riportati in
+\tabref{tab:file_permission_const}; questi sono modificati dalla maschera di
+creazione dei file (si veda \secref{sec:file_umask}). La titolarità della
+nuova directory è impostata secondo quanto riportato in
+\secref{sec:file_ownership}.
+
+La funzione per la cancellazione di una directory è \funcd{rmdir}, il suo
+prototipo è:
+\begin{prototype}{sys/stat.h}{int rmdir(const char *dirname)}
+ Cancella una directory.
+
+ \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+ errore, nel qual caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\errcode{EPERM}] Il filesystem non supporta la cancellazione di
+ directory, oppure la directory che contiene \param{dirname} ha lo sticky
+ bit impostato e l'user-ID effettivo del processo non corrisponde al
+ proprietario della directory.
+ \item[\errcode{EACCES}] Non c'è il permesso di scrittura per la directory
+ che contiene la directory che si vuole cancellare, o non c'è il permesso
+ di attraversare (esecuzione) una delle directory specificate in
+ \param{dirname}.
+ \item[\errcode{EBUSY}] La directory specificata è la directory di lavoro o la
+ radice di qualche processo.
+ \item[\errcode{ENOTEMPTY}] La directory non è vuota.
+ \end{errlist}
+ ed inoltre anche \errval{EFAULT}, \errval{ENAMETOOLONG}, \errval{ENOENT},
+ \errval{ENOTDIR}, \errval{ENOMEM}, \errval{ELOOP}, \errval{EROFS}.}
+\end{prototype}
+
+La funzione cancella la directory \param{dirname}, che deve essere vuota (la
+directory deve cioè contenere soltanto le due voci standard \file{.} e
+\file{..}). Il nome può essere indicato con il pathname assoluto o relativo.
+
+La modalità con cui avviene la cancellazione è analoga a quella di
+\func{unlink}: fintanto che il numero di link all'inode\index{inode} della
+directory non diventa nullo e nessun processo ha la directory aperta lo spazio
+occupato su disco non viene rilasciato. Se un processo ha la directory aperta
+la funzione rimuove il link all'inode\index{inode} e nel caso sia l'ultimo,
+pure le voci standard \file{.} e \file{..}, a questo punto il kernel non
+consentirà di creare più nuovi file nella directory.
+
+
+\subsection{La creazione di file speciali}
+\label{sec:file_mknod}
+
+Finora abbiamo parlato esclusivamente di file, directory e link simbolici; in
+\secref{sec:file_file_types} abbiamo visto però che il sistema prevede pure
+degli altri tipi di file speciali, come i file di dispositivo
+\index{file!di dispositivo}
+e le fifo (i socket\index{socket} sono un caso a parte, che
+vedremo in \capref{cha:socket_intro}).
+
+La manipolazione delle caratteristiche di questi file e la loro cancellazione
+può essere effettuata con le stesse funzioni che operano sui file regolari; ma
+quando li si devono creare sono necessarie delle funzioni apposite. La prima
+di queste funzioni è \funcd{mknod}, il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/stat.h}
+ \headdecl{fnctl.h}
+ \headdecl{unistd.h}
+ \funcdecl{int mknod(const char *pathname, mode\_t mode, dev\_t dev)}
+
+ Crea un inode, si usa per creare i file speciali.
+
+ \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+ errore, nel qual caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\errcode{EPERM}] Non si hanno privilegi sufficienti a creare l'inode, o
+ il filesystem su cui si è cercato di creare \func{pathname} non supporta
+ l'operazione.
+ \item[\errcode{EINVAL}] Il valore di \param{mode} non indica un file, una
+ fifo o un dispositivo.
+ \item[\errcode{EEXIST}] \param{pathname} esiste già o è un link simbolico.
+ \end{errlist}
+ ed inoltre anche \errval{EFAULT}, \errval{EACCES}, \errval{ENAMETOOLONG},
+ \errval{ENOENT}, \errval{ENOTDIR}, \errval{ENOMEM}, \errval{ELOOP},
+ \errval{ENOSPC}, \errval{EROFS}.}
+\end{functions}
+
+La funzione permette di creare un file speciale, ma si può usare anche per
+creare file regolari e fifo; l'argomento \param{mode} specifica il tipo di
+file che si vuole creare ed i relativi permessi, secondo i valori riportati in
+\tabref{tab:file_mode_flags}, che vanno combinati con un OR binario. I
+permessi sono comunque modificati nella maniera usuale dal valore di
+\var{umask} (si veda \secref{sec:file_umask}).
+
+Per il tipo di file può essere specificato solo uno fra: \const{S\_IFREG} per
+un file regolare (che sarà creato vuoto), \const{S\_IFBLK} per un device a
+blocchi, \const{S\_IFCHR} per un device a caratteri e \const{S\_IFIFO} per una
+fifo. Un valore diverso comporterà l'errore \errcode{EINVAL}. Qualora si sia
+specificato in \param{mode} un file di dispositivo, il valore di \param{dev}
+viene usato per indicare a quale dispositivo si fa riferimento.
+
+Solo l'amministratore può creare un file di dispositivo o un file regolare
+usando questa funzione; ma in Linux\footnote{la funzione non è prevista dallo
+ standard POSIX, e deriva da SVr4, con appunto questa differenza e diversi
+ codici di errore.} l'uso per la creazione di una fifo è consentito anche
+agli utenti normali.
+
+I nuovi inode\index{inode} creati con \func{mknod} apparterranno al
+proprietario e al gruppo del processo che li ha creati, a meno che non si sia
+attivato il bit \acr{sgid} per la directory o sia stata attivata la semantica
+BSD per il filesystem (si veda \secref{sec:file_ownership}) in cui si va a
+creare l'inode\index{inode}.
+
+Per creare una fifo (un file speciale, su cui torneremo in dettaglio in
+\secref{sec:ipc_named_pipe}) lo standard POSIX specifica l'uso della funzione
+\funcd{mkfifo}, il cui prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h} \headdecl{sys/stat.h}
+
+ \funcdecl{int mkfifo(const char *pathname, mode\_t mode)}
+
+ Crea una fifo.
+
+ \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+ errore, nel qual caso \var{errno} assumerà i valori \errval{EACCES},
+ \errval{EEXIST}, \errval{ENAMETOOLONG}, \errval{ENOENT}, \errval{ENOSPC},
+ \errval{ENOTDIR} e \errval{EROFS}.}
+\end{functions}
+
+La funzione crea la fifo \param{pathname} con i permessi \param{mode}. Come
+per \func{mknod} il file \param{pathname} non deve esistere (neanche come link
+simbolico); al solito i permessi specificati da \param{mode} vengono
+modificati dal valore di \var{umask}.
+
+
+
+\subsection{Accesso alle directory}
+\label{sec:file_dir_read}
+
+Benché le directory alla fine non siano altro che dei file che contengono
+delle liste di nomi ed inode, per il ruolo che rivestono nella struttura del
+sistema, non possono essere trattate come dei normali file di dati. Ad
+esempio, onde evitare inconsistenze all'interno del filesystem, solo il kernel
+può scrivere il contenuto di una directory, e non può essere un processo a
+inserirvi direttamente delle voci con le usuali funzioni di scrittura.
+
+Ma se la scrittura e l'aggiornamento dei dati delle directory è compito del
+kernel, sono molte le situazioni in cui i processi necessitano di poterne
+leggere il contenuto. Benché questo possa essere fatto direttamente (vedremo
+in \secref{sec:file_open} che è possibile aprire una directory come se fosse
+un file, anche se solo in sola lettura) in generale il formato con cui esse
+sono scritte può dipendere dal tipo di filesystem, tanto che, come riportato
+in \tabref{tab:file_file_operations}, il VFS del kernel prevede una apposita
+funzione per la lettura delle directory.
+
+Tutto questo si riflette nello standard POSIX\footnote{le funzioni sono
+ previste pure in BSD e SVID.} che ha introdotto una apposita interfaccia per
+la lettura delle directory, basata sui cosiddetti \textit{directory stream}
+(chiamati così per l'analogia con i file stream dell'interfaccia standard di
+\capref{cha:files_std_interface}). La prima funzione di questa interfaccia è
+\funcd{opendir}, il cui prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h} \headdecl{dirent.h}
+
+ \funcdecl{DIR * opendir(const char *dirname)}
+
+ Apre un \textit{directory stream}.
+
+ \bodydesc{La funzione restituisce un puntatore al \textit{directory stream}
+ in caso di successo e \val{NULL} per un errore, nel qual caso \var{errno}
+ assumerà i valori \errval{EACCES}, \errval{EMFILE}, \errval{ENFILE},
+ \errval{ENOENT}, \errval{ENOMEM} e \errval{ENOTDIR}.}
+\end{functions}
+
+La funzione apre un \textit{directory stream} per la directory
+\param{dirname}, ritornando il puntatore ad un oggetto di tipo \type{DIR} (che
+è il tipo opaco\index{tipo!opaco} usato dalle librerie per gestire i
+\textit{directory stream}) da usare per tutte le operazioni successive, la
+funzione inoltre posiziona lo stream sulla prima voce contenuta nella
+directory.