+directories. Tutto quello che riguarda invece la manipolazione del contenuto
+dei file è lasciato ai capitoli successivi.
+
+
+\section{La gestione di file e directory}
+
+Le prime funzioni che considereremo sono quelle relative alla gestione di file
+e directory, secondo le caratteristiche standard che essi presentano in un
+filesystem unix, già esaminate in precedenza (vedi
+\secref{sec:fileintr_filesystem}).
+
+\subsection{Le funzioni \texttt{link} e \texttt{unlink}}
+\label{sec:fileintr_link}
+
+Una delle caratteristiche usate quando si opera con i file è quella di poter
+creare dei nomi fittizi (alias o collegamenti) per potersi riferire allo
+stesso file accedendovi da directory diverse. Questo è possibile anche in
+ambiente unix, dove tali collegamenti sono usualmente chiamati \textit{link},
+ma data la struttura del sistema ci sono due metodi sostanzialmente diversi
+per fare questa operazione.
+
+Come si è appena detto l'accesso al contenuto di un file su disco avviene
+attraverso il suo inode, e il nome che si trova in una directory è solo una
+etichetta associata ad un puntatore a detto inode. Questo significa che la
+realizzazione di un link è immediata in quanto uno stesso file può avere tanti
+nomi diversi allo stesso tempo, dati da altrettante diverse associazioni allo
+stesso inode; si noti poi che nessuno di questi nomi viene ad assumere una
+particolare preferenza rispetto agli altri.
+
+Per aggiungere un nome ad un inode si utilizza la funzione \texttt{link}; si
+suole chiamare questo tipo di associazione un collegamento diretto (o
+\textit{hard link}). Il prototipo della funzione e le sue caratteristiche
+principali, come risultano dalla man page, sono le seguenti:
+\begin{prototype}{unistd.h}
+{int link(const char * oldpath, const char * newpath)}
+ Crea un nuovo collegamento diretto al file indicato da \texttt{oldpath}
+ dandogli nome \texttt{newpath}.
+
+ La funzione restituisce zero in caso di successo e -1 per un errore, in caso
+ di errore. La variabile \texttt{errno} viene settata secondo i seguenti
+ codici di errore:
+ \begin{errlist}
+ \item \texttt{EXDEV} \texttt{oldpath} e \texttt{newpath} non sono sullo
+ stesso filesystem.
+ \item \texttt{EPERM} il filesystem che contiene \texttt{oldpath} e
+ \texttt{newpath} non supporta i link diretti o è una directory.
+ \item \texttt{EFAULT} una delle stringhe passate come parametri è fuori
+ dello spazio di indirizzi del processo.
+ \item \texttt{EACCESS} errore di accesso (mancano i permessi per scrivere o
+ per attraversare le directories), vedi \secref{sec:filedir_access_control}
+ per i dettagli.
+ \item \texttt{ENAMETOOLONG} una dei due pathname è troppo lungo.
+ \item \texttt{ENOENT} un componente di \texttt{oldpath} o \texttt{newpath}
+ non esiste o è un link simbolico spezzato.
+ \item \texttt{ENOTDIR} un componente di \texttt{oldpath} o \texttt{newpath}
+ non è una directory.
+ \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a
+ completare l'operazione.
+ \item \texttt{EROFS} la directory su cui si vuole inserire il nuovo link è
+ su un filesystem montato readonly.
+ \item \texttt{EEXIST} un file (o una directory) con quel nome esiste di
+ già.
+ \item \texttt{EMLINK} ci sono troppi link al file \texttt{oldpath} (il
+ numero massimo è specificato dalla variabile \texttt{LINK\_MAX}, vedi
+ \secref{sec:xxx_limits}).
+ \item \texttt{ELOOP} si incontrati troppi link simbolici nella risoluzione
+ di \texttt{oldpath} o \texttt{newpath}.
+ \item \texttt{ENOSPC} la directory in cui si vuole creare il link non ha
+ spazio per ulteriori voci.
+ \item \texttt{EIO} c'è stato un errore di input/output.
+ \end{errlist}
+\end{prototype}
+
+La creazione di un nuovo collegamento diretto non copia il contenuto del file,
+ma si limita ad aumentare di uno il numero di referenze al file aggiungendo il
+nuovo nome ai precedenti. Si noti che uno stesso file può essere così
+richiamato in diverse directory.
+
+Per quanto dicevamo in \secref{sec:fileintr_filesystem} la creazione del
+collegamento diretto è possibile solo se entrambi i pathname sono nello stesso
+filesystem; inoltre il filesystem deve supportare i collegamenti diretti (non è
+il caso ad esempio del filesystem \texttt{vfat} di windows).
+
+La funzione opera sui file ordinari, come sugli altri oggetti del filesystem,
+ma solo l'amministratore è in grado di creare un collegamento diretto ad
+un'altra directory, questo lo si fa perché in questo caso è possibile creare
+dei circoli nel filesystem (vedi \secref{sec:fileintr_symlink}) che molti
+programmi non sono in grado di gestire e la cui rimozione diventa estremamente
+complicata (in genere occorre far girare il programma \texttt{fsck} per
+riparare il filesystem); data la sua pericolosità in Linux questa
+caratteristica è stata disabilitata, e la funzione restituisce l'errore
+\texttt{EPERM}.
+
+La rimozione di un file (o più precisamente della voce che lo referenzia) si
+effettua con la funzione \texttt{unlink}; il suo prototipo è il seguente:
+
+\begin{prototype}{unistd.h}{int unlink(const char * pathname)}
+ Cancella il nome specificato dal pathname nella relativa directory e
+ decrementa il numero di riferimenti nel relativo inode. Nel caso di link
+ simbolico cancella il link simbolico; nel caso di socket, fifo o file di
+ dispositivo rimuove il nome, ma come per i file i processi che hanno aperto
+ uno di questi oggetti possono continuare ad utilizzarlo.
+
+ La funzione restituisce zero in caso di successo e -1 per un errore, nel
+ qual caso il file non viene toccato. La variabile \texttt{errno} viene
+ settata secondo i seguenti codici di errore:
+ \begin{errlist}
+ \item \texttt{EACCESS} errore di accesso (mancano i permessi per scrivere o
+ per attraversare le directories), vedi \secref{sec:filedir_access_control}
+ per i dettagli.
+ \item \texttt{EISDIR} \texttt{pathname} si riferisce ad una directory
+ (valore specifico ritornato da linux che non consente l'uso di
+ \texttt{unlink} con le directory, e non conforme allo standard POSIX, che
+ prescrive invece l'uso di \texttt{EPERM} in caso l'operazione non sia
+ consnetita o il processo non abbia privilegi sufficienti).
+ \item \texttt{EFAULT} la stringa
+ passata come parametro è fuori dello spazio di indirizzi del processo.
+ \item \texttt{ENAMETOOLONG} il pathname troppo lungo.
+ \item \texttt{ENOENT} uno dei componenti del pathname non esiste o è un link
+ simbolico spezzato.
+ \item \texttt{ENOTDIR} uno dei componenti del pathname non è una directory.
+ \item \texttt{EISDIR} \texttt{pathname} fa riferimento a una directory.
+ \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a
+ completare l'operazione.
+ \item \texttt{EROFS} \texttt{pathname} è su un filesystem montato in sola
+ lettura.
+ \item \texttt{ELOOP} ci sono troppi link simbolici nella risoluzione del
+ pathname.
+ \item \texttt{EIO} errore di input/output.
+ \end{errlist}
+\end{prototype}
+
+Per cancellare una voce in una directory è necessario avere il permesso di
+scrittura su di essa (dato che si va a rimuovere una voce dal suo contenuto) e
+il diritto di esecuzione sulla directory che la contiene (torneremo in
+dettaglio sui permessi e gli attributi fra poco), se inoltre lo
+\textit{sticky} bit è settato occorrerà anche essere proprietari del file o
+proprietari della directory (o root, per cui nessuna delle restrizioni è
+applicata).
+
+Una delle caratteristiche di queste funzioni è che la creazione/rimozione
+della nome dalla directory e l'incremento/decremento del numero di riferimenti
+nell'inode deve essere una operazione atomica (cioè non interrompibile da
+altri) processi, per questo entrambe queste funzioni sono realizzate tramite
+una singola system call.
+
+Si ricordi infine che il file non viene eliminato dal disco fintanto che tutti
+i riferimenti ad esso sono stati cancellati, solo quando il \textit{link
+ count} mantenuto nell'inode diventa zero lo spazio occupato viene rimosso. A
+questo però si aggiunge una altra condizione, e cioè che non ci siano processi
+che abbiano detto file aperto. Come accennato questa proprietà viene spesso
+usata per essere sicuri di non lasciare file temporanei su disco in caso di
+crash dei programmi; la tecnica è quella di aprire il file e chiamare
+\texttt{unlink} subito dopo.
+
+\subsection{Le funzioni \texttt{remove} e \texttt{rename}}
+\label{sec:fileintr_remove}
+
+Al contrario di quanto avviene con altri unix in Linux non è possibile usare
+\texttt{unlink} sulle directory, per cancellare una directory si può usare la
+funzione \texttt{rmdir} (vedi \secref{sec:filedir_dir_creat_rem}), oppure la
+funzione \texttt{remove}. Questa è la funzione prevista dallo standard ANSI C
+per cancellare un file o una directory (e funziona anche per i sistemi che non
+supportano i link diretti), che per i file è identica alla \texttt{unlink} e
+per le directory è identica alla \texttt{rmdir}:
+
+\begin{prototype}{stdio.h}{int remove(const char *pathname)}
+ Cancella un nome dal filesystem. Usa \texttt{unlink} per i file e
+ \texttt{rmdir} per le directory.
+
+ La funzione restituisce zero in caso di successo e -1 per un errore, nel
+ qual caso il file non viene toccato. Per i codici di errori vedi quanto
+ riportato nella descrizione di \texttt{unlink} e \texttt{rmdir}.
+\end{prototype}
+
+Per cambiare nome ad un file si usa invece la funzione \texttt{rename}, il
+vantaggio nell'uso di questa funzione al posto della chiamata successiva di
+\texttt{unlink} e \texttt{link} è che l'operazione è eseguita atomicamente, in
+questo modo non c'è la possibilità che un processo che cerchi di accedere al
+nuovo nome dopo che il vecchio è stato cambiato lo trovi mancante.
+
+\begin{prototype}{stdio.h}
+{int rename(const char *oldpath, const char *newpath)}
+ Rinomina un file, spostandolo fra directory diverse quando richiesto.
+
+ La funzione restituisce zero in caso di successo e -1 per un errore, nel
+ qual caso il file non viene toccato. La variabile \texttt{errno} viene
+ settata secondo i seguenti codici di errore:
+ \begin{errlist}
+ \item \texttt{EISDIR} \texttt{newpath} è una directory già esistente mentre
+ \texttt{oldpath} non è una directory.
+ \item \texttt{EXDEV} \texttt{oldpath} e \texttt{newpath} non sono sullo
+ stesso filesystem.
+ \item \texttt{ENOTEMPTY} \texttt{newpath} è una directory già esistente e
+ non vuota.
+ \item \texttt{EBUSY} o \texttt{oldpath} o \texttt{newpath} sono in uso da
+ parte di qualche processo (come directory di lavoro o come root) o del
+ sistema (come mount point).
+ \item \texttt{EINVAL} \texttt{newpath} contiene un prefisso di
+ \texttt{oldpath} o più in generale si è cercato di creare una directory
+ come sottodirectory di se stessa.
+ \item \texttt{EMLINK} \texttt{oldpath} ha già il massimo numero di link
+ consentiti o è una directory e la directory che contiene \texttt{newpath}
+ ha già il massimo numero di link.
+ \item \texttt{ENOTDIR} Uno dei componenti dei pathname non è una directory
+ o\texttt{oldpath} è una directory e \texttt{newpath} esiste e non è una
+ directory.
+ \item \texttt{EFAULT} o \texttt{oldpath} o \texttt{newpath} è fuori dello
+ spazio di indirizzi del processo.
+ \item \texttt{EACCESS} Non c'è il permesso di scrittura per la directory in
+ cui si vuole creare il nuovo link o una delle directory del pathname non
+ consente la ricerca (permesso di esecuzione).
+ \item \texttt{EPERM} le directory contenenti \texttt{oldpath} o
+ \texttt{newpath} hanno lo sticky bit attivo e i permessi del processo non
+ consentono rispettivamente la cancellazione e la creazione del file, o il
+ filesystem non supporta i link.
+ \item \texttt{ENAMETOOLONG} uno dei pathname è troppo lungo.
+ \item \texttt{ENOENT} Uno dei componenti del pathname non esiste o è un link
+ simbolico spezzato.
+ \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a
+ completare l'operazione.
+ \item \texttt{EROFS} I file sono su un filesystem montato in sola lettura.
+ \item \texttt{ELOOP} Ci sono troppi link simbolici nella risoluzione del
+ pathname.
+ \item \texttt{ENOSPC} Il device di destinazione non ha più spazio per la
+ nuova voce.
+ \end{errlist}
+\end{prototype}
+
+\subsection{I link simbolici}
+\label{sec:fileintr_symlink}
+
+Siccome la funzione \texttt{link} crea riferimenti agli inodes, essa può
+funzionare soltanto per file che risiedono sullo stesso filesystem, dato che
+in questo caso è garantita l'unicità dell'inode, e solo per un filesystem di
+tipo unix. Inoltre in Linux non è consentito eseguire un link diretto ad una
+directory.
+
+Per ovviare a queste limitazioni i sistemi unix supportano un'altra forma di
+link (i cosiddetti \textit{soft link} o \textit{symbolic link}), che sono,
+come avviene in altri sistemi operativi, dei file che contengono il
+semplicemente il riferimento ad un altro file (o directory). In questo modo è
+possibile effettuare link anche attraverso filesystem diversi e a directory, e
+pure a file che non esistono ancora.
+
+Il sistema funziona in quanto i link simbolici sono contrassegnati come tali
+al kernel (analogamente a quanto avviene per le directory) per cui la chiamata
+ad una \texttt{open} o una \texttt{stat} su un link simbolico comporta la
+lettura del contenuto del medesimo e l'applicazione della funzione al file
+specificato da quest'ultimo. Invece altre funzioni come quelle per cancellare
+o rinominare i file operano direttamente sul link simbolico. Inoltre esistono
+funzioni apposite, come la \texttt{readlink} e la \texttt{lstat} per accedere
+alle informazioni del link invece che a quelle del file a cui esso fa
+riferimento.
+
+Le funzioni per operare sui link simbolici sono le seguenti, esse sono tutte
+dichiarate nell'header file \texttt{unistd.h}.
+
+\begin{prototype}{unistd.h}
+{int symlink(const char * oldname, const char * newname)}
+ Crea un nuovo link simbolico al file indicato da \texttt{oldname} dandogli
+ nome \texttt{newname}.
+
+ La funzione restituisce zero in caso di successo e -1 per un errore, in caso
+ di errore. La variabile \texttt{errno} viene settata secondo i codici di
+ errore standard di accesso ai files (trattati in dettaglio in
+ \secref{sec:filedir_access_control}) ai quali si aggiungono i seguenti:
+ \begin{errlist}
+ \item \texttt{EEXIST} Un file (o una directory) con quel nome esiste di
+ già.
+ \item \texttt{EROFS} La directory su cui si vuole inserire il nuovo link è
+ su un filesystem montato readonly.
+ \item \texttt{ENOSPC} La directory o il filesystem in cui si vuole creare il
+ link è piena e non c'è ulteriore spazio disponibile.
+ \item \texttt{ELOOP} Ci sono troppi link simbolici nella risoluzione di
+ \texttt{oldname} o di \texttt{newname}.
+ \end{errlist}
+\end{prototype}
+
+Dato che la funzione \texttt{open} segue i link simbolici, è necessaria usare
+un'altra funzione quando si vuole leggere il contenuto di un link simbolico,
+questa funzione è la:
+
+\begin{prototype}{unistd.h}
+{int readlink(const char * path, char * buff, size\_t size)}
+ Legge il contenuto del link simbolico indicato da \texttt{path} nel buffer
+ \texttt{buff} di dimensione \texttt{size}. Non chiude la stringa con un
+ carattere nullo e la tronca a \texttt{size} nel caso il buffer sia troppo
+ piccolo per contenerla.
+
+ La funzione restituisce il numero di caratteri letti dentro \texttt{buff} o
+ -1 per un errore, in caso di errore. La variabile \texttt{errno} viene
+ settata secondo i codici di errore:
+ \begin{errlist}
+ \item \texttt{EEXIST} Un file (o una directory) con quel nome esiste di
+ già.
+ \item \texttt{EROFS} La directory su cui si vuole inserire il nuovo link è
+ su un filesystem montato readonly.
+ \item \texttt{ENOSPC} La directory o il filesystem in cui si vuole creare il
+ link è piena e non c'è ulteriore spazio disponibile.
+ \item \texttt{ELOOP} Ci sono troppi link simbolici nella risoluzione di
+ \texttt{oldname} o di \texttt{newname}.
+ \end{errlist}
+\end{prototype}
+
+\section{La manipolazione delle directories}
+\label{sec:filedir_dir_handling}
+
+\subsection{Le funzioni \texttt{mkdir} e \texttt{rmdir}}
+\label{sec:filedir_dir_creat_rem}
+
+Per creare una nuova directory si può usare la seguente funzione, omonima
+dell'analogo comando di shell \texttt{mkdir}; per accedere ai tipi usati
+programma deve includere il file \texttt{sys/types.h}.
+
+\begin{prototype}{sys/stat.h}
+{int mkdir (const char * dirname, mode\_t mode)}
+ Questa funzione crea una nuova directory vuota con il nome indicato da
+ \texttt{dirname}, assegnandole i permessi indicati da \texttt{mode}. Il nome
+ può essere indicato con il pathname assoluto o relativo.
+
+ La funzione restituisce zero in caso di successo e -1 per un errore, in caso
+ di errore \texttt{errno} viene settata secondo i codici di errore standard
+ di accesso ai files (trattati in dettaglio in
+ \secref{sec:filedir_access_control}) ai quali si aggiungono i seguenti:
+ \begin{errlist}
+ \item \texttt{EACCESS}
+ Non c'è il permesso di scrittura per la directory in cui si vuole inserire
+ la nuova directory.
+ \item \texttt{EEXIST} Un file (o una directory) con quel nome esiste di già.
+ \item \texttt{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 nell'hard-disk, ma potendo avere a che
+ fare anche con filesystem di altri sistemi questo errore può presentarsi.
+ \item \texttt{ENOSPC} Non c'è abbastanza spazio sul file system per creare
+ la nuova directory.
+ \item \texttt{EROFS} La directory su cui si vuole inserire la nuova
+ directory è su un filesystem montato readonly.
+ \end{errlist}
+\end{prototype}
+
+
+\subsection{Accesso alle directory}
+\label{sec:filedir_dir_read}
+
+Benché le directory siano oggetti del filesystem come tutti gli altri non ha
+ovviamente senso aprirle come fossero dei file di dati. Può però essere utile
+poterne leggere il contenuto ad esempio per fare la lista dei file che esse
+contengono o ricerche sui medesimi.
+
+Per accedere al contenuto delle directory si usano i cosiddetti
+\textit{directory streams} (chiamati così per l'analogia con i file stream);
+la funzione \texttt{opendir} apre uno di questi stream e la funzione
+\texttt{readdir} legge il contenuto della directory, i cui elementi sono le
+\textit{directory entries} (da distinguersi da quelle della cache di cui
+parlavamo in \secref{sec:fileintr_vfs}) in una opportuna struttura
+\texttt{struct dirent}.
+
+
+\subsection{La directory di lavoro}
+\label{sec:filedir_work_dir}
+
+A ciascun processo è associato ad 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 (relativa appunto a questa directory).
+
+Quando un utente effettua il login questa directory viene settata alla
+cosiddetta \textit{home directory} del suo account, il comando \texttt{cd}
+della shell consente di cambiarla a piacere, spostandosi da una directory ad
+un'altra. Siccome la directory corrente resta la stessa quando viene creato
+un processo figlio, la directory corrente della shell diventa anche la
+directory corrente di qualunque comando da essa lanciato.
+
+Le funzioni qui descritte servono esaminare e cambiare la directory di lavoro
+corrente.
+
+\begin{prototype}{unistd.h}{char * getcwd (char * buffer, size\_t size)}
+ Restituisce il filename completo della directory di lavoro corrente nella
+ stringa puntata da \texttt{buffer}, che deve essere precedentemente
+ allocata, per una dimensione massima di \texttt{size}. Si può anche
+ specificare un puntatore nullo come \textit{buffer}, nel qual caso la
+ stringa sarà allocata automaticamente per una dimensione pari a
+ \texttt{size} qualora questa sia diversa da zero, o della lunghezza esatta
+ del pathname altrimenti. In questo caso si deve ricordare di disallocare la
+ stringa una volta cessato il suo utilizzo.
+
+ La funzione restituisce il puntatore \texttt{buffer} se riesce,
+ \texttt{NULL} se fallisce, in quest'ultimo caso la variabile
+ \texttt{errno} è settata con i seguenti codici di errore:
+ \begin{errlist}
+ \item \texttt{EINVAL} L'argomento \texttt{size} è zero e \texttt{buffer} non
+ è nullo.
+ \item \texttt{ERANGE} L'argomento \texttt{size} è più piccolo della
+ lunghezza del pathname.
+ \item \texttt{EACCESS} 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}
+
+Di questa funzione esiste una versione \texttt{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 \texttt{PATH\_MAX} (di solito 256 bytes, vedi
+\secref{sec:xxx_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 è \texttt{char * get\_current\_dir\_name(void)}
+che è sostanzialmente equivalente ad una \texttt{getcwd(NULL, 0)}, con la sola
+differenza che essa ritorna il valore della variabile di ambiente
+\texttt{PWD}, che essendo costruita dalla shell può contenere anche dei
+riferimenti simbolici.
+
+Come già detto in unix anche le directory sono file, è possibile pertanto
+riferirsi ad esse tramite il file descriptor dell'interfaccia a basso livello,
+e non solo tramite il filename; per questo motivo ci sono due diverse funzioni
+per cambiare directory di lavoro.
+
+\begin{prototype}{unistd.h}{int chdir (const char * pathname)}
+ Come dice il nome (che significa \textit{change directory}) questa funzione
+ serve a cambiare la directory di lavoro a quella specificata dal pathname
+ contenuto nella stringa \texttt{pathname}.
+\end{prototype}
+
+\begin{prototype}{unistd.h}{int fchdir (int filedes)}
+ Analoga alla precedente, ma usa un file descriptor invece del pathname.
+
+ Entrambe le funzioni restituiscono zero in caso di successo e -1 per un
+ errore, in caso di errore \texttt{errno} viene settata secondo i codici di
+ errore standard di accesso ai files (trattati in dettaglio in
+ \secref{sec:filedir_access_control}) ai quali si aggiunge il codice
+ \texttt{ENOTDIR} nel caso il \texttt{filename} indichi un file che non sia
+ una directory.
+\end{prototype}