Roba di ieri, riscritte meglio (spero) alcune parti
[gapil.git] / files.tex
index badd9edfd3d4bf9cd051c1ee4f82c7ed33b5770c..e3c994d5b96e735ac94acd5f21a453256e04607a 100644 (file)
--- a/files.tex
+++ b/files.tex
@@ -1,44 +1,55 @@
-\chapter{I files}
+\chapter{I files: introduzione}
 \label{cha:files}
-
 Uno dei concetti fondamentali del design di unix è il cosiddetto
-\textit{everything is a file}, cioè il fatto che l'accesso alle periferiche
-viene gestito attraverso un'interfaccia astratta che tratta nello stesso modo
-sia i normali file di dati che le periferiche. Si può accedere cioè a queste
-ultime (con l'eccezione delle interfacce di rete) attraverso i cosiddetti file
-di dispositivo (i \textit{device files}) che permettono ai programmi di
-interfacciarsi alle varie periferiche come la seriale, la parallela, la
-console, e gli stessi dischi.
-
-\section{Concetti generali sui files}
+\textit{everything is a file}, cioè il fatto che l'accesso ai vari dispositivi
+di I/O del computer viene effettuato attraverso un'interfaccia astratta che
+tratta le periferiche allo stesso modo degli usuali file di dati.
+
+Si può accedere cioè a qualunque periferica del computer, dalla seriale, alla
+parallela, alla console, e agli stessi dischi, (unica eccezione le interfacce
+di rete, che che non rientrano bene nell'astrazione) attraverso i cosiddetti
+file di dispositivo (i \textit{device files}). Questi sono dei file speciali
+agendo sui quali i programmi possono leggere, scrivere e compiere operazioni
+sulle perferiche, usando le stesse funzioni che si usano per i normali file di
+dati.
+
+\section{Concetti generali riguardanti i files}
 \label{sec:file_gen}
 
-Per poter accedere ai singoli file su disco è necessario l'uso di un
-\textit{filesystem}, cioè di un'interfaccia del kernel che permetta di
-strutturare l'informazione tenuta sullo spazio grezzo disponibile sui dischi
-in files e directory. Sarà quest'ultimo a gestire l'accesso ai dati
-memorizzati all'interno del disco stesso, e l'uso delle normali directory e
-files.
+Visto il ruolo fondamentale che i files vengono ad assumere in un sistema
+unix, è anzitutto opportuno fornire un'introduzione dettagliata su come essi
+vengono trattati dal sistema. In particolare occorre tenere presente dov'è che
+si situa il limite fondamentale fra kernel space e user space che tracciavamo
+al Cap.~\ref{cha:intro_unix}.
+
+Partiamo allora da come viene strutturata nel sistema la disposizione dei
+file: per potervi accedere il kernel usa una apposita interfaccia che permetta
+di strutturare l'informazione tenuta sullo spazio grezzo disponibile sui
+dischi, cioè quello che si chiama un \textit{filesystem}. 
+
+Sarà attraverso quest'ultimo che il kernel andrà a gestire l'accesso ai dati
+memorizzati all'interno del disco stesso, strutturando l'informazione in files
+e directory.  Per poter accedere ai file contenuti in un disco occorrerà
+perciò attivare il filesystem, questo viene fatto \textsl{montando} il disco
+(o la partizione del disco).
 
 %In generale un filesystem piazzerà opportunamente sul disco dei blocchi di
 %informazioni riservate che tengono conto degli inodes allocati, di quelli
 %liberi, e delle posizioni fisiche su disco dei dati contenuti nei files, per
 
-Per poter accedere ai file contenuti in un disco occorrerà poi attivare il
-filesystem \textit{montando} il disco (o la partizione del disco). 
-
-In unix, a differenza di quanto avviene in altri sistemi operativi, tutti i
+In Unix, a differenza di quanto avviene in altri sistemi operativi, tutti i
 file vengono tenuti all'interno di un unico albero la cui radice (la directory
 di \textit{root}) viene montata all'avvio. Pertanto un file viene identificato
-dall'utente usando il suo \textit{pathname}, cioè il percorso completo che si
-deve fare a partire dalla radice, per accedere al file.
+dall'utente usando quello che viene chiamato \textit{pathname}, cioè il
+percorso completo che si deve fare a partire dalla radice, per accedere al
+file.
 
 Dopo la fase di inizializzazione il kernel riceve dal boot loader
 l'indicazione di quale dispositivo contiene il filesystem da usare come punto
 di partenza e questo viene montato come radice dell'albero (cioè nella
 directory \texttt{/}); tutti gli ulteriori dischi devono poi essere inseriti
-nell'albero utilizzando opportune subdirectory (in genere sotto
-\texttt{/mnt}) .
+nell'albero utilizzando opportune subdirectory.
 
 Alcuni filesystem speciali (come \texttt{/proc} che contiene un'interfaccia ad
 alcune strutture interne del kernel) sono generati automaticamente dal kernel
@@ -71,19 +82,19 @@ coesistenza di diversi filesystem all'interno dello stesso kernel.
 
 La funzione più importante implementata dal VFS è la system call \texttt{open}
 che permette di aprire un file. Dato un pathname viene eseguita una ricerca
-dentro la \textit{directory entry cache} (la \textit{dcache}) una tabella di
-hash che contiene tutte le \textit{directory entry} (in breve \textit{dentry})
-che permette di associare in maniera rapida ed efficiente il pathname a una
-specifica dentry.
+dentro la \textit{directory entry cache} (in breve \textit{dcache}) che è
+una tabella di hash che contiene tutte le \textit{directory entry} (in breve
+\textit{dentry}) che permette di associare in maniera rapida ed efficiente il
+pathname a una specifica dentry.
 
 Una singola dentry contiene in genere il puntatore ad un \textit{inode};
 quest'ultimo è la struttura base che sta sul disco e che identifica un singolo
-oggetto del VFS che può essere un file, una directory, una FIFO, un file di
-dispositivo, o una qualsiasi altra cosa che possa essere rappresentata dal
-VFS (sui tipi di files possibili torneremo in seguito).
+oggetto del VFS sia esso un file ordinario, una directory, una FIFO, un file
+di dispositivo, o una qualsiasi altra cosa che possa essere rappresentata dal
+VFS (sui tipi di ``files'' possibili torneremo in seguito).
 
 Le dentries ``vivono'' in memoria e non vengono mai salvate su disco, vengono
-usate per motivi di velocità, gli inodes invece vivono su disco e vengono
+usate per motivi di velocità, gli inodes invece stanno su disco e vengono
 copiati in memoria quando serve, ed ogni cambiamento viene copiato
 all'indietro sul disco, gli inodes che stanno in memoria sono inodes del VFS
 ed è ad essi che puntano le singole dentry.
@@ -111,11 +122,6 @@ user space possono accedere alle operazioni attraverso detti metodi, che
 saranno diversi a seconda del tipo di file (o dispositivo) aperto. Un elenco
 delle operazioni disponibili è riportato in \ntab.
 
-% La struttura file viene poi inserita nella tavola dei file
-% , non
-% tutte le operazioni possibili sono definite per tutti i dispositivi; un elenco
-% delle operazioni definite in linux è riportato in \ntab.
-
 \begin{table}[htb]
   \centering
   \begin{tabular}[c]{c p{7cm}}
@@ -149,32 +155,33 @@ utilizzare la opportuna routine dichiarata in \verb|f_ops| appropriata al tipo
 di file in questione. 
 
 Così sarà possibile scrivere sulla porta seriale come su un file di dati
-normale; ovviamente certe operazioni (nel caso la \textit{seek}) non saranno
-disponibili, però con questo sistema l'utilizzo di diversi filesystem è
-immediato e (relativamente) trasparente per l'utente ed il programmatore.
+normale; ovviamente certe operazioni (nel caso della seriale ad esempio la
+\textit{seek}) non saranno disponibili, però con questo sistema l'utilizzo di
+diversi filesystem (come quelli usati da Windows o MacOs) è immediato e
+(relativamente) trasparente per l'utente ed il programmatore.
 
 \subsection{Proprietari e permessi}
 \label{sec:file_perms}
 
-In unix è implementata da qualunque filesystem standard una forma elementare
+In Unix è implementata da qualunque filesystem standard una forma elementare
 (ma adatta alla maggior parte delle esigenze) di controllo di accesso ai
 files. Torneremo sull'argomento in dettaglio più avanti, qui ci limitiamo ad
 una introduzione dei concetti essenziali.
 
-Si tenga conto poi che quanto diremo è vero solo per filesystem di tipo unix,
+Si tenga conto poi che quanto diremo è vero solo per filesystem di tipo Unix,
 e non è detto che sia applicabile (ed infatti non è vero per il filesystem di
-windows) a un filesystem qualunque. Esistono inoltre estensioni che permettono
+Windows) a un filesystem qualunque. Esistono inoltre estensioni che permettono
 di implementare le ACL (\textit{Access Control List}) che sono un meccanismo
 di controllo di accesso molto più sofisticato.
 
-Ad ogni file unix associa sempre l'utente che ne è proprietario (il cosiddetto
+Ad ogni file Unix associa sempre l'utente che ne è proprietario (il cosiddetto
 \textit{owner}) e il gruppo di appartenenza, secondo il meccanismo degli uid e
 gid spiegato in \ref{sec:intro_usergroup}, e un insieme di permessi che sono
 divisi in tre classi, e cioè attribuiti rispettivamente al proprietario, a
 qualunque utente faccia parte del gruppo cui appartiene il file, e a tutti gli
 altri utenti.
 
-I permessi sono espressi da un insieme di 12 bit, di questi i nove meno
+I permessi sono espressi da un insieme di 12 bit: di questi i nove meno
 significativi sono usati a gruppi di tre per indicare i permessi base di
 lettura, scrittura ed esecuzione (indicati rispettivamente con le lettere
 \textit{w}, \textit{r} \textit{x}) applicabili rispettivamente al
@@ -220,7 +227,7 @@ dei vari tipi di file 
       \textit{fifo} & \textsl{tubo} &
       un file speciale che identifica una linea di comunicazione software
       (unidirezionale) \\
-      \textit{socket} & \textsl{presa} &
+      \textit{socket} & \textsl{manicotto} &
       un file speciale che identifica una linea di comunicazione software
       (bidirezionale) \\
     \hline
@@ -233,26 +240,27 @@ dei vari tipi di file 
 Tutto ciò non ha ovviamente nulla a che fare con la classificazione sui tipi
 di file (in questo caso file di dati) in base al loro contenuto, o tipo di
 accesso.  Una delle differenze principali con altri sistemi operativi (come il
-VMS o windows) è che per unix tutti i file di dati sono identici e contengono
+VMS o Windows) è che per Unix tutti i file di dati sono identici e contengono
 un flusso continuo di bytes; non esiste cioè differenza per come vengono visti
 dal sistema file di diverso contenuto o formato (come nel caso di quella fra
 file di testo e binari che c'è in windows) né c'è una strutturazione a record
 per il cosiddetto ``accesso diretto'' come nel caso del VMS.
 
-Una seconda differenza è nel formato dei file ascii; in unix la fine riga è
-codificata in maniera diversa da windows o macintosh, in particolare il fine
-riga è il carattere \texttt{LF} al posto del \texttt{CR} del mac e del
-\texttt{CR LF} di windows. Questo può causare alcuni problemi qualora si
-facciano assunzioni sul terminatore della riga.
+Una seconda differenza è nel formato dei file ascii; in Unix la fine riga è
+codificata in maniera diversa da Windows o MacIntosh, in particolare il fine
+riga è il carattere \texttt{LF} (o \verb|\n|) al posto del \texttt{CR}
+(\verb|\r|) del mac e del \texttt{CR LF} di windows. Questo può causare alcuni
+problemi qualora si facciano assunzioni sul terminatore della riga.
 
 
-\section{Una panoramica sull'I/O sui file}
+\section{Una panoramica sull'uso dei file}
 \label{sec:file_io_base}
 
 Per poter accedere al contenuto dei file occorre anzitutto aprirlo. Questo
 crea un canale di comunicazione che permette di eseguire una serie di
 operazioni. Una volta terminate le operazioni, il file dovrà essere chiuso, e
-questo chiuderà il canale di comunicazione impedendo ogni ulteriore operazione.
+questo chiuderà il canale di comunicazione impedendo ogni ulteriore
+operazione.
 
 
 \subsection{Le due interfacce ai file}
@@ -262,14 +270,14 @@ In unix le modalit
 programmazione sono due, basate su due diversi meccanismi di connessione. 
 
 La prima è quella dei cosiddetti \textit{file descriptor} (descrittore di
-file), che è specifica di unix e che provvede un accesso diretto a basso
+file), che è specifica di Unix e che provvede un accesso diretto a basso
 livello non bufferizzato, con un'interfaccia primitiva ed essenziale; i file
 descriptors sono rappresentati da numeri interi (cioè semplici variabili di
 tipo \texttt{int}). L'interfaccia è definita nell'header \texttt{unistd.h}.
 
 La seconda è quella degli \textit{stream}, che provvede un'interfaccia più
 evoluta e un accesso bufferizzato. Questa è anche l'interfaccia standard usata
-dal linguaggio C e perciò si trova anche su tutti i sistemi non unix. Gli
+dal linguaggio C e perciò si trova anche su tutti i sistemi non Unix. Gli
 stream sono oggetti complessi e sono rappresentati da puntatori ad un
 opportuna struttura definita dalle librerie del C, si accede ad essi sempre in
 maniera indiretta utilizzando il tipo \texttt{FILE *}. L'interfaccia è
@@ -289,8 +297,8 @@ l'eccezione di poter scegliere tre diversi stili di bufferizzazione.  Il
 maggior vantaggio degli stream è che l'interfaccia per le operazioni di
 input/output è enormemente più ricca di quella dei file descriptor, che
 provvedono solo funzioni elementari per la lettura/scrittura diretta di
-blocchi di bytes.  In particolare dispongono di tutte le funzioni di
-formattazione per l'input e l'output adatte per manipolare anche i dati in
+blocchi di bytes.  In particolare gli stream dispongono di tutte le funzioni
+di formattazione per l'input e l'output adatte per manipolare anche i dati in
 forma di linee o singoli caratteri.
 
 In ogni caso, dato che gli stream sono implementati sopra l'interfaccia a
@@ -308,7 +316,7 @@ pertanto di portabilit
 \label{sec:files_spec_unix}
 
 Essendo un sistema multitasking e multiutente esistono alcune caratteristiche
-specifiche di unix che devono essere tenute in conto nell'accesso ai file. È
+specifiche di Unix che devono essere tenute in conto nell'accesso ai file. È
 infatti normale che più processi o programmi possano accedere
 contemporaneamente allo stesso file e devono poter eseguire le loro operazioni
 indipendentemente da quello che fanno gli altri processi.
@@ -327,26 +335,25 @@ sistemi POSIX uno degli attributi di un file aperto 
 file, cioè il punto nel file in cui verrebbe letto o scritto alla operazione
 successiva. Essa è rappresentata da un numero intero che indica il numero di
 bytes dall'inizio del file, che viene (a meno che non si apra il file in
-append) inizializzato a zero all'apertura del medesimo. 
-
+append) inizializzato a zero all'apertura del medesimo.
 
 Questo è uno dei dati che viene mantenuto nella suddetta struttura, per cui
 ogni processo avrà la sua posizione corrente nel file, che non sarà
 influenzata da quello che altri processi possono fare. Anzi, aprire un file
 significa appunto creare ed inizializzare una tale struttura, per cui se si
 apre due volte lo stesso file all'interno dello stesso processo, si otterrano
-due file descriptor o due stream che avranno ancora un posizione corrente nel
+due file descriptor o due stream che avranno ancora una posizione corrente nel
 file assolutamente indipendente.
 
 Si tenga conto inoltre che un'altro dei dati contenuti nella struttura di
 accesso è un riferimento all'inode del file, pertanto anche se il file viene
-cancellato da un altro processo, sarà sempre possibile mantenere l'accesso,
-e lo spazio su disco non verrà rilasciato fintanto che il file non sarà chiuso
-e l'ultimo riferimento cancellato. È pertanto possibile (e pratica comune)
-aprire un file provvisorio per cancellarlo immediatamente dopo; in questo modo
-all'uscita del programma il file scomparirà definitivamente dal disco, ma il
-file ed il suo contenuto saranno disponibili per tutto il tempo in cui il
-processo è attivo.
+cancellato da un altro processo, sarà sempre possibile mantenere l'accesso ai
+dati, e lo spazio su disco non verrà rilasciato fintanto che il file non sarà
+chiuso e l'ultimo riferimento cancellato. È pertanto possibile (e pratica
+comune) aprire un file provvisorio per cancellarlo immediatamente dopo; in
+questo modo all'uscita del programma il file scomparirà definitivamente dal
+disco, ma il file ed il suo contenuto saranno disponibili per tutto il tempo
+in cui il processo è attivo.
 
 
 \subsection{L'accesso ai files: nomi e directory}
@@ -366,12 +373,12 @@ semplicemente specificando il nome da essa contenuto. Una directory contiene
 semplicemente un elenco di questi componenti, che possono corrispondere a un
 qualunque oggetto del filesystem, compresa un'altra directory.
 
-Un nome di file è composto da una serie di componenti separati da una
+Un nome di file è composto da una serie di \textsl{componenti} separati da una
 \texttt{/} (in linux più \texttt{/} consecutive sono considerate equivalenti
 ad una sola). Il nome completo di un file viene usualmente chiamato
-\textit{pathname}, anche se questo può generare confusione, dato che con
-\textit{path} si indica anche un insieme di directory su cui effettuare una
-ricerca (ad esempio quello in cui si cercano i comandi).
+\textit{filename} o \textit{pathname}, anche se quest'ultimo può generare
+confusione, dato che con \textit{path} si indica anche un insieme di directory
+su cui effettuare una ricerca (ad esempio quello in cui si cercano i comandi).
 
 Il processo con cui si associa ad un pathname uno specifico file (cioè si
 identifica l'inode a cui fare riferimento) è chiamato risoluzione del nome
@@ -387,8 +394,8 @@ del processo che (a meno di un \textit{chroot} su cui torneremo in seguito,
 vedi \ref{sec:file_chroot}) è la stessa per tutti i processi ed equivale alla
 radice dell'albero (\ref{sec:file_gen}): in questo caso si parla di un
 pathname \textsl{assoluto}. Altrimenti la ricerca parte dalla directory
-corrente (su cui pure torneremo più avanti in \ref{sec:file_cwd}) ed il
-pathname è detto \textsl{relativo}.
+corrente (su cui pure torneremo più avanti in \ref{sec:file_dir_working}) ed
+il pathname è detto \textsl{relativo}.
 
 I componenti \texttt{.} e \texttt{..} hanno un significato speciale e vengono
 inseriti in ogni directory, il primo fa riferimento alla directory corrente e
@@ -396,11 +403,11 @@ il secondo alla directory \textsl{genitore} (\textit{parent directory}) cio
 la directory che contiene il riferimento alla directory corrente; nel caso
 questa sia la directory radice allora il riferimento è a se stessa.
 
-Infine si ricordi che in unix non esistono i tipi di file e che non c'è nessun
+Infine si ricordi che in Unix non esistono i tipi di file e che non c'è nessun
 supporto per le estensioni come parte del filesystem. Ciò non ostante molti
 programmi adottano delle convenzioni per i nomi dei file, ad esempio il codice
-C normalmente si mette in file con l'estensione .c, ma questa è solo una
-convenzione.
+C normalmente si mette in file con l'estensione .c, ma questa è, appunto, solo
+una convenzione.
 
 
 \section{L'interfaccia al filesystem}
@@ -413,7 +420,7 @@ che permettono di esaminare e modificare le directory, rinominare o cancellare
 i file, esaminare o settare i loro attributi.
 
 \subsection{La directory di lavoro}
-\label{sec:file_dir_cvd}
+\label{sec:file_dir_working}
 
 Come accennato ciascun processo è associato ad una directory nel filesystem
 che è chiamata directory corrente o directory di lavoro (\textit{current
@@ -428,24 +435,23 @@ 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. I prototipi di queste funzioni sono dichiarati in
-\texttt{unistd.h}. 
+corrente. I prototipi di queste funzioni sono dichiarati in \texttt{unistd.h}. 
 
 \begin{itemize}
-\item \texttt{char * getcwd (char * buffer, size_t size)}
+\item \texttt{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 \texiti{buffer}, nel qual caso la
+  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 disallocara 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 sono ritornate le seguenti
-  condizioni di errore:
+  \texttt{NULL} se fallisce, in quest'ultimo caso la variabile
+  \texttt{errno} è settata con i seguenti codici di errore:
 
   \begin{itemize}
   \item \texttt{EINVAL} L'argomento \texttt{size} è zero e \texttt{buffer} non
@@ -458,6 +464,205 @@ corrente. I prototipi di queste funzioni sono dichiarati in
   \end{itemize}
 \end{itemize}
 
+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 byters, vedi
+\ref{sec:xxxx_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
+(come vedremo in \ref{sec:file_dir_access}) 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{itemize}
+\item \texttt{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 speficata dal pathname
+  contenuto nella stringa \texttt{pathname}.
+  
+\item \texttt{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
+  \ref{sec:file_err_acc}) ai quali si aggiunge il codice \texttt{ENOTDIR} nel
+  caso il \texttt{filename} indichi un file che non sia una directory.
+\end{itemize}
+
+\subsection{Creazione di una directory} 
+\label{sec:file_dir_creat}
+
+Per creare una nuova directory si può usare la seguente funzione, omonima
+dell'analogo comando di shell \texttt{mkdir}; per accedere alla funzioni il
+programma deve includere il file \texttt{sys/stat.h}.
+
+\begin{itemize}
+\item \texttt{char * 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 \ref{sec:file_err_acc}) ai
+  quali si aggiungono i seguenti:
+  \begin{itemize}
+  \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 essite 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{itemize}
+\end{itemize}
+
+\subsection{Accesso alle directory}
+\label{sec:file_dir_access}
+
+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 \ref{sec:file_vfs}) in una opportuna struttura \texttt{struct
+dirent}.
+
+\subsection{I link simbolici e i link diretti}
+\label{sec:file_link}
+
+Una delle caratteristiche più 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 è già accennato nell'introduzione in un sistema unix l'accesso al
+contenuto di un file su disco avviene attraverso il suo \textit{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 links è
+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}, e si
+suole chiamare questa associazione un collegamento diretto (o \textit{hard
+  link}).  La creazione di un nuovo link diretto non copia il contenuto del
+file, ma si limita ad aumentare di uno il numero di referenze al file (uno dei
+dati contenuti nell'inode) aggiungendo il nuovo nome ai precedenti. Si noti
+che uno stesso file può essere così richiamato in diverse directory.
+
+Siccome tutto ciò funziona facendo riferimento ad un inode, questa funzione
+può essere applicata soltanto per file che risiedono sullo stesso filesystem,
+(dato che solo in questo caso è garantita l'unicità dell'inode) e solo per
+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 sono le seguenti, esse sono tutte dichiarate
+nell'header file \texttt{unistd.h}.
+
+\begin{itemize}
+\item \texttt{int link(const char * oldname, const char * newname)}
+  
+  Crea un nuovo link diretto 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
+  \ref{sec:file_err_acc}) ai quali si aggiungono i seguenti:
+
+  \begin{itemize}
+  \item \texttt{EXDEV} \texttt{oldname} e \texttt{newname} non sono sullo
+    stesso filesystem.
+  \item \texttt{EPERM} il filesystem che contiene \texttt{oldname} e
+    \texttt{newname} non supporta i link diretti.
+  \item \texttt{EACCESS} 
+    Non c'è il permesso di scrittura per la directory in cui si vuole creare
+    il nuovo link.
+  \item \texttt{EEXIST} Un file (o una directory) con quel nome esiste di
+    già.
+  \item \texttt{EMLINK} Ci sono troppi link al file \texttt{oldname} (il
+    numero massimo è specificato dalla variabile \texttt{LINK\_MAX}, vedi
+    \ref{sec:sys_limits}.
+  \item \texttt{ENOSPC} La directory in cui si vuole creare il link è piena e
+    non può essere ampliata.
+  \item \texttt{EROFS} La directory su cui si vuole inserire il nuovo link è
+    su un filesystem montato readonly.
+  \end{itemize}
+\end{itemize}
+
+
+\begin{itemize}
+\item \texttt{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
+  \ref{sec:file_err_acc}) ai quali si aggiungono i seguenti:
+
+  \begin{itemize}
+  \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{itemize}
+\end{itemize}
+
+
 
 
 \section{L'input/output di basso livello}