\chapter{Files e directories}
\label{cha:files_and_dirs}
-In questo capitolo tratteremo in dettaglio le varie caratteristiche di files e
-directories, ed in particolare approfondiremo i dettagli su come è organizzata
-la struttura dei files in un sistema unix, esamineremo come è strutturato il
+In questo capitolo tratteremo in dettaglio le modalità con cui si gestiscono
+files e directories, ed in particolare esamineremo come è strutturato il
sistema base di protezioni e controllo di accesso ai files, e tutta
l'interfaccia che permette la manipolazione dei vari attributi di files e
directories. Tutto quello che riguarda invece la manipolazione dei contenuti è
lasciato ai capitoli successivi.
-\section{L'organizzazione di files e directories}
-\label{sec:filedir_org}
-
-L'organizzazione dei nomi dei file deriva direttamente dall'organizzazione dei
-medesimi nell'albero descritto brevemente in \secref{sec:fileintr_overview};
-una directory comunque, come già specificato in \secref{sec:fileintr_vfs}, è
-solo un particolare tipo di file che contiene le informazioni che associano un
-nome al contenuto. Per questo, anche se è usuale parlare di ``file in una
-directory'' in realtà una directory contiene solo delle etichette per fare
-riferimento ai file stessi.
-
-I manuale delle librerie del C chiama i nomi contenuti nelle directory
-\textsl{componenti} (in inglese \textit{file name components}), noi li
-chiameremo più semplicemente nomi. Un file può essere indicato rispetto alla
-directory corrente semplicemente specificando il nome da essa contenuto. Una
-directory contiene semplicemente un elenco di questi nomi, che possono
-corrispondere a un qualunque oggetto del filesystem, compresa un'altra
-directory; l'albero viene appunto creato inserendo directory in altre
-directory.
-
-Il nome completo di file generico è composto da una serie di questi
-\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}, e anche se il manuale della
-glibc depreca questo nome (poiché genererebbe confusione, dato che con
-\textit{path} si indica anche un insieme di directory su cui effettuare una
-ricerca, come quello in cui si cercano i comandi) l'uso è ormai così comune
-che è senz'altro più chiaro dell'alternativa proposta.
-
-Il processo con cui si associa ad un pathname uno specifico file è chiamato
-risoluzione del nome (\textit{file name resolution} o \textit{pathname
- resolution}). La risoluzione viene fatta esaminando il pathname da destra a
-sinistra e localizzando ogni nome nella directory indicata dal nome
-precedente: ovviamente perché il procedimento funzioni occorre che i nomi
-indicati come directory esistano e siano effettivamente directory, inoltre i
-permessi devono consentire l'accesso.
-
-Se il pathname comincia per \texttt{/} la ricerca parte dalla directory radice
-del processo; questa, a meno di un \textit{chroot} (su cui torneremo in
-seguito, vedi \secref{sec:xxx_chroot}) è la stessa per tutti i processi ed
-equivale alla directory radice dell'albero (come descritto in
-\secref{sec:fileintr_overview}): in questo caso si parla di un pathname
-\textsl{assoluto}. Altrimenti la ricerca parte dalla directory corrente (su
-cui torneremo più avanti in \secref{sec:filedir_work_dir}) ed il pathname è
-detto \textsl{relativo}.
-
-I nomi \texttt{.} e \texttt{..} hanno un significato speciale e vengono
-inseriti in ogni directory, il primo fa riferimento alla directory corrente e
-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.
-
-
-\section{L'architettura della gestione dei file}
-\label{sec:filedir_file_handling}
-
-Per capire fino in fondo le proprietà di files e directories in un sistema
-unix ed il funzionamento delle relative funzioni di manipolazione occorre una
-breve introduzione sulla gestione dei medesimo e sugli oggetti su cui è basato
-un filesystem unix; in particolare si riprenderà, approfondendolo sul piano
-dell'uso nelle funzioni di libreria, il concetto di \textit{inode} di cui
-abbiamo brevemente accennato le caratteristiche (dal lato dell'implementazione
-nel kernel) in \secref{sec:fileintr_vfs}.
-
-
-\subsection{Il funzionamento di un filesystem unix}
-\label{sec:filedir_filesystem}
-
-Come già accennato in \secref{sec:fileintr_overview} Linux (ed ogni unix in
-generale) organizza i dati che tiene su disco attraverso l'uso di un
-filesystem. Una delle caratteristiche di Linux rispetto agli altri unix è
-quella di poter supportare grazie al VFS una enorme quantità di filesystem
-diversi, ognuno dei quali ha una sua particolare struttura e funzionalità
-proprie; per questo non entreremo nei dettagli di un filesystem specifico, ma
-daremo una descrizione a grandi linee che si adatta alle caratteristiche
-comuni di un qualunque filesystem standard unix.
-
-Dato un disco lo spazio fisico viene usualmente diviso in partizioni; ogni
-partizione può contenere un filesystem; quest'ultimo è in genere strutturato
-secondo \nfig, con una lista di inodes all'inizio e il resto dello spazio a
-disposizione per i dati e le directory.
-
-\begin{figure}[htb]
- \centering
-
- \caption{Organizzazione dello spazio su un disco in partizioni e filesystem}
- \label{fig:filedir_disk_filesys}
-\end{figure}
-
-Se si va ad esaminare come è strutturata l'informazione all'interno di un
-singolo filesystem (tralasciando le parti connesse alla strutturazione e al
-funzionamento del filesystem stesso come il super-block) avremo una situazione
-del tipo di quella esposta in \nfig.
-\begin{figure}[htb]
- \centering
-
- \caption{Organizzazione di un filesystem}
- \label{fig:filedir_filesys_detail}
-\end{figure}
-da questa figura si evidenziano alcune caratteristiche su cui è bene porre
-attenzione in quanto sono fondamentali per capire il funzionamento delle
-funzioni che manipolano i file e le directory su cui torneremo fra poco; in
-particolare è opportuno ricordare sempre che:
-
-\begin{enumerate}
-
-\item L'\textit{inode} contiene tutte le informazioni riguardanti il file: il
- tipo di file, i permessi di accesso, le dimensioni, i puntatori ai blocchi
- fisici che contengono i dati e così via; le informazioni che la funzione
- \texttt{stat} fornisce provengono dall'\textit{inode}; dentro una directory
- si troverà solo il nome del file e il numero dell'\textit{inode} ad esso
- associato, cioè quella che da qui in poi chiameremo una \textsl{voce}
- (traduzione approssimata dell'inglese \textit{directory entry}, che non
- useremo anche per evitare confusione con le \textit{dentries} del kernel di
- cui si parlava in \secref{sec:fileintr_vfs}).
-
-\item Come mostrato in \curfig si possono avere più voci che puntano allo
- stesso \textit{inode}. Ogni \textit{inode} ha un contatore che contiene il
- numero di riferimenti (\textit{link count}) che sono stati fatti ad esso;
- solo quando questo contatore si annulla i dati del file vengono
- effettivamente rimossi dal disco. Per questo la funzione per cancellare un
- file si chiama \texttt{unlink}, ed in realtà non cancella affatto i dati del
- file, ma si limita a eliminare la relativa voce da una directory e
- decrementare il numero di riferimenti nell'\textit{inode}.
-
-\item Il numero di \textit{inode} nella voce si riferisce ad un \textit{inode}
- nello stesso filesystem e non ci può essere una directory che contiene
- riferimenti ad \textit{inodes} relativi ad altri filesystem. Questo limita
- l'uso del comando \texttt{ln} (che crea una nuova voce per un file
- esistente, con la funzione \texttt{link}) al filesystem corrente.
-
-\item Quando si cambia nome ad un file senza cambiare filesystem il contenuto
- del file non deve essere spostato, viene semplicemente creata una nuova voce
- per l'\textit{inode} in questione e rimossa la vecchia (questa è la modalità
- in cui opera normalmente il comando \texttt{mv} attraverso la funzione
- \texttt{rename}).
-
-\end{enumerate}
-
-Infine è bene avere presente che essendo file pure loro, esiste un numero di
-riferimenti anche per le directories; per cui se ad esempio a partire dalla
-situazione mostrata in \curfig\ creiamo una nuova directory \texttt{textdir}
-nella directory corrente avremo una situazione come quella in \nfig, dove per
-chiarezza abbiamo aggiunto dei numeri di inode.
-
-La nuova directory avrà allora un numero di riferimenti pari a due, in quanto
-è referenziata dalla directory da cui si era partiti (in cui è inserita la
-nuova voce che fa riferimento a \texttt{textdir}) e dalla voce \texttt{.}
-che è sempre inserita in ogni directory; questo vale sempre per ogni directory
-che non contenga a sua volta altre directories. Al contempo la directory da
-cui si era partiti avrà un numero di riferiementi di almeno tre, in quanto
-adesso sarà referenziata anche dalla voce \texttt{..} di \texttt{textdir}.
-
-
-\subsection{Le funzioni \texttt{link} e \texttt{unlink}}
-\label{sec:filedir_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:filedir_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:filedir_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:filedir_cre_canc}
-
-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:filedir_sym_link}
-
-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 caratteristiche dei files}
\label{sec:filedir_infos}
effettivamente usata nel kernel dipende dall'archietettura e ha altri campi
riservati per estensioni come tempo più precisi, o per il padding dei campi).
-\begin{figure}[!htbp]
+\begin{figure}[!htb]
\footnotesize
- \begin{lstlisting}{}
+ \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}[]{}
struct stat {
dev_t st_dev; /* device */
ino_t st_ino; /* inode */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last change */
};
- \end{lstlisting}
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
\caption{La struttura \texttt{stat} per la lettura delle informazioni dei
file}
\label{fig:sock_sa_gen_struct}
+
\subsection{I tipi di file}
\label{sec:filedir_file_types}
\label{sec:filedir_access_control}
+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 (vedi
+\secref{sec:filedir_access_control}), qui ci limitiamo ad una introduzione dei
+concetti essenziali.
+
+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
+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
+\textit{owner}) e il gruppo di appartenenza, secondo il meccanismo degli uid e
+gid accennato in \secref{sec:intro_multiuser}, 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
+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
+proprietario, al gruppo, a tutti (una descrizione più dettagliata dei vari
+permessi associati ai file è riportata in \secref{sec:filedir_suid_sgid}). I
+restanti tre bit sono usati per indicare alcune caratteristiche più complesse
+(\textit{suid}, \textit{sgid}, e \textit{sticky}) su cui pure torneremo in
+seguito (vedi \secref{sec:filedir_suid_sgid} e \secref{sec:filedir_sticky}).
+
+Tutte queste informazioni sono tenute per ciascun file nell'inode. Quando un
+processo cerca l'accesso al file esso controlla i propri uid e gid
+confrontandoli con quelli del file e se l'operazione richiesta è compatibile
+con i permessi associati al file essa viene eseguita, altrimenti viene
+bloccata ed è restituito un errore di \texttt{EPERM}. Questo procedimento non
+viene eseguito per l'amministratore di sistema (il cui uid è zero) il quale ha
+pertanto accesso senza restrizione a qualunque file del sistema.
+
+% In realtà il procedimento è più complesso di quanto descritto in maniera
+% elementare qui; inoltre ad un processo sono associati diversi identificatori,
+% torneremo su questo in maggiori dettagli in seguito in \secref{sec:proc_perms}.
+
+
+
\subsection{I flag \texttt{suid} e \texttt{sgid}}
\label{sec:filedir_suid_sgid}
-\chapter{I files: introduzione}
+\chapter{I files: l'architettura}
\label{cha:files_intro}
Uno dei concetti fondamentali della architettura di unix è il cosiddetto
\textit{everything is a file}, cioè il fatto che l'accesso ai vari dispositivi
di input/output del computer viene effettuato attraverso un'interfaccia
-astratta che tratta le periferiche allo stesso modo degli usuali file di
-dati.
+astratta che tratta le periferiche allo stesso modo degli usuali file di dati.
Questo significa che si può accedere cioè a qualunque periferica del computer,
dalla seriale, alla parallela, alla console, e agli stessi dischi attraverso i
operazioni direttamente sulle periferiche, usando le stesse funzioni che si
usano per i normali file di dati.
-In questo capitolo forniremo un'introduzione alle principali caratteristiche
-di questa interfaccia, su come essa viene implementata in Linux e su come sono
-organizzati i file nel sistema.
+In questo capitolo forniremo un'introduzione all'architettura della gestione
+dei file, sia nelle sue caratteristiche generiche comuni a tutti gli unix, che
+nelle particolarità che ha la specifica implementazione usata da Linux. Al
+comtempo tratteremo l'organizzazione dei file in un sistema unix-like, e le
+varie caratteristiche distintive.
-\section{I file in un sistema unix-like}
-\label{sec:fileintr_overview}
+
+\section{L'organizzazione di files e directories}
+\label{sec:filedir_org}
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 \capref{cha:intro_unix}.
+unix-like, è anzitutto opportuno fornire un'introduzione dettagliata su come
+essi vengono organizzati all'interno del sistema.
+
+
+\subsection{Una breve introduzione}
+\label{sec:fileintr_org_intro}
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} (useremo per brevità
-questo nome al posto della più prolissa traduzione italiana sistema di file).
+dischi, cioè quello che si chiama un \textit{filesystem}\footnote{useremo per
+ brevità questo nome al posto della più prolissa traduzione italiana sistema
+ di file}, che descriviremo in dettaglio in \secref{sec:fileintr_vfs}.
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 (su questo aspetto torneremo con maggiori dettagli in
-\secref{sec:filedir_filesystem}). 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).
+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
link, i socket e gli stessi i file di dispositivo (questi ultimi, per
convenzione, sono inseriti nella directory \texttt{/dev}).
-\subsection{Il \textit{virtual filesystem} di Linux}
-\label{sec:fileintr_vfs}
-Esamineremo adesso come viene implementato l'accesso ai files in Linux. Questa
-sezione riporta informazioni sui dettagli di come il kernel gestisce i files.
-L'argomento è abbastanza ``esoterico'' e questa sezione può essere saltata ad
-una prima lettura; è bene però tenere presente che vengono introdotti qui
-alcuni termini che potranno comparire in seguito, come \textit{inode},
-\textit{dentry}, \textit{dcache}.
+\subsection{La struttura di file e directories}
+\label{sec:fileintr_filedir_struct}
+
+L'organizzazione dei nomi dei file deriva direttamente dall'organizzazione dei
+medesimi nell'albero descritto brevemente in \secref{sec:fileintr_org_intro};
+una directory comunque, come già specificato in \secref{sec:fileintr_vfs}, è
+solo un particolare tipo di file che contiene le informazioni che associano un
+nome al contenuto. Per questo, anche se è usuale parlare di ``file in una
+directory'' in realtà una directory contiene solo delle etichette per fare
+riferimento ai file stessi.
+
+I manuale delle glibc chiama i nomi contenuti nelle directory
+\textsl{componenti} (in inglese \textit{file name components}), noi li
+chiameremo più semplicemente nomi. Un file può essere indicato rispetto alla
+directory corrente semplicemente specificando il nome da essa contenuto. Una
+directory contiene semplicemente un elenco di questi nomi, che possono
+corrispondere a un qualunque oggetto del filesystem, compresa un'altra
+directory; l'albero viene appunto creato inserendo directory in altre
+directory.
+
+Il nome completo di file generico è composto da una serie di questi
+\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}, e anche se il manuale della
+glibc depreca questo nome (poiché genererebbe confusione, dato che con
+\textit{path} si indica anche un insieme di directory su cui effettuare una
+ricerca, come quello in cui si cercano i comandi) l'uso è ormai così comune
+che è senz'altro più chiaro dell'alternativa proposta.
+
+Il processo con cui si associa ad un pathname uno specifico file è chiamato
+risoluzione del nome (\textit{file name resolution} o \textit{pathname
+ resolution}). La risoluzione viene fatta esaminando il pathname da destra a
+sinistra e localizzando ogni nome nella directory indicata dal nome
+precedente: ovviamente perché il procedimento funzioni occorre che i nomi
+indicati come directory esistano e siano effettivamente directory, inoltre i
+permessi devono consentire l'accesso.
+
+Se il pathname comincia per \texttt{/} la ricerca parte dalla directory radice
+del processo; questa, a meno di un \textit{chroot} (su cui torneremo in
+seguito, vedi \secref{sec:xxx_chroot}) è la stessa per tutti i processi ed
+equivale alla directory radice dell'albero (come descritto in
+\secref{sec:fileintr_overview}): in questo caso si parla di un pathname
+\textsl{assoluto}. Altrimenti la ricerca parte dalla directory corrente (su
+cui torneremo più avanti in \secref{sec:filedir_work_dir}) ed il pathname è
+detto \textsl{relativo}.
+
+I nomi \texttt{.} e \texttt{..} hanno un significato speciale e vengono
+inseriti in ogni directory, il primo fa riferimento alla directory corrente e
+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.
+
+
+% \subsection{Il controllo di accesso}
+% \label{sec:fileintr_access_ctrl}
-In Linux il concetto di \textit{everything is a file} è stato implementato
-attraverso il \textit{virtual filesystem} (da qui in avanti VFS) che è
-l'interfaccia che il kernel rende disponibile ai programmi in user space
-attraverso la quale vengono manipolati i files; esso provvede un livello di
-indirezione che permette di collegare le operazioni di manipolazione sui files
-alle operazioni di I/O e gestisce l'organizzazione di questi ultimi nei vari
-modi in cui diversi filesystem la effettuano, permettendo la coesistenza
-di filesystem differenti all'interno dello stesso albero delle directory
-
-Quando un processo esegue una system call che opera su un file il kernel
-chiama sempre una funzione implementata nel VFS; la funzione eseguirà le
-manipolazioni sulle strutture generiche e ridirigendo la chiamata alla
-opportune routine del filesystem specifico a cui si fa riferimento, saranno
-queste a chiamare le funzioni di piu basso livello che eseguono le operazioni
-di I/O sul dispositivo fisico, secondo lo schema riportato in \nfig.
-
-\begin{figure}[htb]
- \centering
-
- \caption{Schema delle operazioni del VFS}
- \label{fig:fileintro_VFS_scheme}
-\end{figure}
-
-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} (in breve \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.
-
-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 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). A ciascuno di essi
-è associata pure una struttura che sta in memoria, e che oltre alle
-informazioni sullo specifico file contiene pure il riferimento alle funzioni
-(i \textsl{metodi}) da usare per poterlo manipolare.
-
-Le dentries ``vivono'' in memoria e non vengono mai salvate su disco, 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.
-
-La dcache costituisce perciò una sorta di vista completa di tutto l'albero dei
-files, ovviamente per non riempire tutta la memoria questa vista è parziale
-(la dcache cioè contiene solo le dentry per i file per i quali è stato
-richiesto l'accesso), quando si vuole risolvere un nuovo pathname il VFS deve
-creare una nuova dentry e caricare l'inode corrispondente in memoria.
-
-Questo procedimento viene eseguito dal metodo \texttt{lookup()} dell'inode
-della directory che contiene il file; questo viene installato nelle relative
-strutture in memoria quando si effettua il montaggio lo specifico filesystem
-su cui l'inode va a vivere.
-
-Una volta che il VFS ha a disposizione la dentry (ed il relativo inode)
-diventa possibile accedere alle varie operazioni sul file come la
-\texttt{open} per aprire il file o la \texttt{stat} per leggere i dati
-dell'inode e passarli in user space.
-
-L'apertura di un file richiede comunque un'altra operazione, l'allocazione di
-una struttura di tipo \texttt{file} in cui viene inserito un puntatore alla
-dentry e una struttura \verb|f_ops| che contiene i puntatori ai metodi che
-implementano le operazioni disponibili sul file. In questo modo i processi in
-user space possono accedere alle operazioni attraverso detti metodi, che
-saranno diversi a seconda del tipo di file (o dispositivo) aperto (su questo
-torneremo in dettaglio in \secref{sec:fileunix_fd}). Un elenco delle operazioni
-previste dal kernel è riportato in \ntab.
-
-\begin{table}[htb]
- \centering
- \begin{tabular}[c]{c p{7cm}}
- \textbf{funzione} & \textbf{operazione} \\
- \hline
- \textit{open} & apre il file \\
- \textit{read} & legge dal file \\
- \textit{write} & scrive sul file \\
- \textit{llseek} & sposta la posizione corrente sul file \\
- \textit{ioctl} & accede alle operazioni di controllo
- (tramite la \texttt{ioctl})\\
- \textit{readdir} & per leggere il contenuto di una directory \\
- \textit{poll} & \\
- \textit{mmap} & chiamata dalla system call \texttt{mmap}.
- mappa il file in memoria\\
- \textit{release} & chiamata quando l'ultima referenza a un file
- aperto è chiusa\\
- \textit{fsync} & chiamata dalla system call \texttt{fsync} \\
- \textit{fasync} & chiamate da \texttt{fcntl} quando è abilitato
- il modo asincrono per l'I/O su file. \\
- \hline
- \end{tabular}
- \caption{Operazioni sui file definite nel VFS.}
- \label{tab:fileintr_file_operations}
-\end{table}
-
-In questo modo per ciascun file diventano utilizzabili una serie di operazioni
-(non è dette che tutte siano disponibili), che costituiscono l'interfaccia
-astratta del VFS, e qualora se ne voglia eseguire una il kernel andrà ad
-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 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{Il controllo di accesso}
-\label{sec:fileintr_access_ctrl}
-
-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 (vedi
-\secref{sec:filedir_access_control}), qui ci limitiamo ad una introduzione dei
-concetti essenziali.
-
-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
-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
-\textit{owner}) e il gruppo di appartenenza, secondo il meccanismo degli uid e
-gid accennato in \secref{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
-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
-proprietario, al gruppo, a tutti (una descrizione più dettagliata dei vari
-permessi associati ai file è riportata in \secref{sec:filedir_suid_sgid}). I
-restanti tre bit sono usati per indicare alcune caratteristiche più complesse
-(\textit{suid}, \textit{sgid}, e \textit{sticky}) su cui pure torneremo in
-seguito (vedi \secref{sec:filedir_suid_sgid} e \secref{sec:filedir_sticky}).
-
-Tutte queste informazioni sono tenute per ciascun file nell'inode. Quando un
-processo cerca l'accesso al file esso controlla i propri uid e gid
-confrontandoli con quelli del file e se l'operazione richiesta è compatibile
-con i permessi associati al file essa viene eseguita, altrimenti viene
-bloccata ed è restituito un errore di \texttt{EPERM}. Questo procedimento non
-viene eseguito per l'amministratore di sistema (il cui uid è zero) il quale ha
-pertanto accesso senza restrizione a qualunque file del sistema.
-
-In realtà il procedimento è più complesso di quanto descritto in maniera
-elementare qui; inoltre ad un processo sono associati diversi identificatori,
-torneremo su questo in maggiori dettagli in seguito in \secref{sec:proc_perms}.
\subsection{I tipi di files}
\label{sec:fileintr_file_types}
-Come detto in precedenza esistono vari tipi di oggetti implementati del VFS
-per i quali è disponibile l'interfaccia astratta da esso provveduta. Un elenco
-dei vari tipi di file definiti nel VFS è il seguente:
+Come detto in precedenza in unix esistono vari tipi di file, in Linux questi
+sono implementati come oggetti del \textit{Virtual File System} e sono
+presenti in tutti i filesystem unix-like utilizzabili con Linux. L'elenco dei
+vari tipi di file definiti dal Virtual File System è il seguente:
\begin{table}[htb]
\begin{center}
\begin{tabular}[c]{l l p{7cm}}
- \multicolumn{2}{c}{\textbf{Nome}} & \textbf{Descrizione} \\
+ \multicolumn{2}{c}{\textbf{Tipo di file}} & \textbf{Descrizione} \\
\hline
\textit{regular file} & \textsl{file normale} &
un file che contiene dei dati (l'accezione normale di file) \\
\end{center}
\end{table}
-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
-un flusso continuo di bytes; non esiste cioè differenza per come vengono visti
+Si tenga ben presente che tutto ciò non ha nulla a che fare con la
+classificazione sui tipi di file (che in questo caso sono sempre 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 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.
riga.
-\section{Una panoramica sull'uso dei file}
-\label{sec:fileintr_io_overview}
-
-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.
-
\subsection{Le due interfacce ai file}
\label{sec:fileintr_io_api}
In unix le modalità di accesso ai file e le relative interfacce di
-programmazione sono due, basate su due diversi meccanismi di connessione.
+programmazione sono due, basate su due diversi meccanismi con cui è possibile
+accedere al loro contenuto.
La prima è l'interfaccia standard di unix, quella che il manuale delle glibc
chiama interfaccia dei descrittore di file (o \textit{file descriptor}). È
un'interfaccia specifica di unix e provvede un accesso non bufferizzato.
+
L'interfaccia è primitiva ed essenziale, l'accesso viene detto non
bufferizzato in quanto la lettura e la scrittura vengono eseguite chiamando
direttamente le system call del kernel (in realtà il kernel effettua al suo
C normalmente si mette in file con l'estensione .c, ma questa è, appunto, solo
una convenzione.
+
+
+\section{L'architettura della gestione dei file}
+\label{sec:filedir_file_handling}
+
+Per capire fino in fondo le proprietà di files e directories in un sistema
+unix ed il funzionamento delle relative funzioni di manipolazione occorre una
+breve introduzione sulla gestione dei medesimo e sugli oggetti su cui è basato
+un filesystem unix; in particolare si riprenderà, approfondendolo sul piano
+dell'uso nelle funzioni di libreria, il concetto di \textit{inode} di cui
+abbiamo brevemente accennato le caratteristiche (dal lato dell'implementazione
+nel kernel) in \secref{sec:fileintr_vfs}.
+
+In particolare occorre tenere presente dov'è che si situa la divisione
+fondamentale fra kernel space e user space che tracciavamo al
+\capref{cha:intro_unix}.
+
+
+\subsection{Il \textit{virtual filesystem} di Linux}
+\label{sec:fileintr_vfs}
+
+Esamineremo adesso come viene implementato l'accesso ai files in Linux. Questa
+sezione riporta informazioni sui dettagli di come il kernel gestisce i files.
+L'argomento è abbastanza ``esoterico'' e questa sezione può essere saltata ad
+una prima lettura; è bene però tenere presente che vengono introdotti qui
+alcuni termini che potranno comparire in seguito, come \textit{inode},
+\textit{dentry}, \textit{dcache}.
+
+In Linux il concetto di \textit{everything is a file} è stato implementato
+attraverso il \textit{virtual filesystem} (da qui in avanti VFS) che è
+l'interfaccia che il kernel rende disponibile ai programmi in user space
+attraverso la quale vengono manipolati i files; esso provvede un livello di
+indirezione che permette di collegare le operazioni di manipolazione sui files
+alle operazioni di I/O e gestisce l'organizzazione di questi ultimi nei vari
+modi in cui diversi filesystem la effettuano, permettendo la coesistenza
+di filesystem differenti all'interno dello stesso albero delle directory
+
+Quando un processo esegue una system call che opera su un file il kernel
+chiama sempre una funzione implementata nel VFS; la funzione eseguirà le
+manipolazioni sulle strutture generiche e ridirigendo la chiamata alla
+opportune routine del filesystem specifico a cui si fa riferimento, saranno
+queste a chiamare le funzioni di piu basso livello che eseguono le operazioni
+di I/O sul dispositivo fisico, secondo lo schema riportato in \nfig.
+
+\begin{figure}[htb]
+ \centering
+
+ \caption{Schema delle operazioni del VFS}
+ \label{fig:fileintro_VFS_scheme}
+\end{figure}
+
+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} (in breve \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.
+
+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 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). A ciascuno di essi
+è associata pure una struttura che sta in memoria, e che oltre alle
+informazioni sullo specifico file contiene pure il riferimento alle funzioni
+(i \textsl{metodi}) da usare per poterlo manipolare.
+
+Le dentries ``vivono'' in memoria e non vengono mai salvate su disco, 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.
+
+La dcache costituisce perciò una sorta di vista completa di tutto l'albero dei
+files, ovviamente per non riempire tutta la memoria questa vista è parziale
+(la dcache cioè contiene solo le dentry per i file per i quali è stato
+richiesto l'accesso), quando si vuole risolvere un nuovo pathname il VFS deve
+creare una nuova dentry e caricare l'inode corrispondente in memoria.
+
+Questo procedimento viene eseguito dal metodo \texttt{lookup()} dell'inode
+della directory che contiene il file; questo viene installato nelle relative
+strutture in memoria quando si effettua il montaggio lo specifico filesystem
+su cui l'inode va a vivere.
+
+Una volta che il VFS ha a disposizione la dentry (ed il relativo inode)
+diventa possibile accedere alle varie operazioni sul file come la
+\texttt{open} per aprire il file o la \texttt{stat} per leggere i dati
+dell'inode e passarli in user space.
+
+L'apertura di un file richiede comunque un'altra operazione, l'allocazione di
+una struttura di tipo \texttt{file} in cui viene inserito un puntatore alla
+dentry e una struttura \verb|f_ops| che contiene i puntatori ai metodi che
+implementano le operazioni disponibili sul file. In questo modo i processi in
+user space possono accedere alle operazioni attraverso detti metodi, che
+saranno diversi a seconda del tipo di file (o dispositivo) aperto (su questo
+torneremo in dettaglio in \secref{sec:fileunix_fd}). Un elenco delle operazioni
+previste dal kernel è riportato in \ntab.
+
+\begin{table}[htb]
+ \centering
+ \begin{tabular}[c]{c p{7cm}}
+ \textbf{funzione} & \textbf{operazione} \\
+ \hline
+ \textit{open} & apre il file \\
+ \textit{read} & legge dal file \\
+ \textit{write} & scrive sul file \\
+ \textit{llseek} & sposta la posizione corrente sul file \\
+ \textit{ioctl} & accede alle operazioni di controllo
+ (tramite la \texttt{ioctl})\\
+ \textit{readdir} & per leggere il contenuto di una directory \\
+ \textit{poll} & \\
+ \textit{mmap} & chiamata dalla system call \texttt{mmap}.
+ mappa il file in memoria\\
+ \textit{release} & chiamata quando l'ultima referenza a un file
+ aperto è chiusa\\
+ \textit{fsync} & chiamata dalla system call \texttt{fsync} \\
+ \textit{fasync} & chiamate da \texttt{fcntl} quando è abilitato
+ il modo asincrono per l'I/O su file. \\
+ \hline
+ \end{tabular}
+ \caption{Operazioni sui file definite nel VFS.}
+ \label{tab:fileintr_file_operations}
+\end{table}
+
+In questo modo per ciascun file diventano utilizzabili una serie di operazioni
+(non è dette che tutte siano disponibili), che costituiscono l'interfaccia
+astratta del VFS, e qualora se ne voglia eseguire una il kernel andrà ad
+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 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{Il funzionamento di un filesystem unix}
+\label{sec:filedir_filesystem}
+
+Come già accennato in \secref{sec:fileintr_overview} Linux (ed ogni unix in
+generale) organizza i dati che tiene su disco attraverso l'uso di un
+filesystem. Una delle caratteristiche di Linux rispetto agli altri unix è
+quella di poter supportare grazie al VFS una enorme quantità di filesystem
+diversi, ognuno dei quali ha una sua particolare struttura e funzionalità
+proprie; per questo non entreremo nei dettagli di un filesystem specifico, ma
+daremo una descrizione a grandi linee che si adatta alle caratteristiche
+comuni di un qualunque filesystem standard unix.
+
+Dato un disco lo spazio fisico viene usualmente diviso in partizioni; ogni
+partizione può contenere un filesystem; quest'ultimo è in genere strutturato
+secondo \nfig, con una lista di inodes all'inizio e il resto dello spazio a
+disposizione per i dati e le directory.
+
+\begin{figure}[htb]
+ \centering
+
+ \caption{Organizzazione dello spazio su un disco in partizioni e filesystem}
+ \label{fig:filedir_disk_filesys}
+\end{figure}
+
+Se si va ad esaminare come è strutturata l'informazione all'interno di un
+singolo filesystem (tralasciando le parti connesse alla strutturazione e al
+funzionamento del filesystem stesso come il super-block) avremo una situazione
+del tipo di quella esposta in \nfig.
+\begin{figure}[htb]
+ \centering
+
+ \caption{Organizzazione di un filesystem}
+ \label{fig:filedir_filesys_detail}
+\end{figure}
+da questa figura si evidenziano alcune caratteristiche su cui è bene porre
+attenzione in quanto sono fondamentali per capire il funzionamento delle
+funzioni che manipolano i file e le directory su cui torneremo fra poco; in
+particolare è opportuno ricordare sempre che:
+
+\begin{enumerate}
+
+\item L'\textit{inode} contiene tutte le informazioni riguardanti il file: il
+ tipo di file, i permessi di accesso, le dimensioni, i puntatori ai blocchi
+ fisici che contengono i dati e così via; le informazioni che la funzione
+ \texttt{stat} fornisce provengono dall'\textit{inode}; dentro una directory
+ si troverà solo il nome del file e il numero dell'\textit{inode} ad esso
+ associato, cioè quella che da qui in poi chiameremo una \textsl{voce}
+ (traduzione approssimata dell'inglese \textit{directory entry}, che non
+ useremo anche per evitare confusione con le \textit{dentries} del kernel di
+ cui si parlava in \secref{sec:fileintr_vfs}).
+
+\item Come mostrato in \curfig si possono avere più voci che puntano allo
+ stesso \textit{inode}. Ogni \textit{inode} ha un contatore che contiene il
+ numero di riferimenti (\textit{link count}) che sono stati fatti ad esso;
+ solo quando questo contatore si annulla i dati del file vengono
+ effettivamente rimossi dal disco. Per questo la funzione per cancellare un
+ file si chiama \texttt{unlink}, ed in realtà non cancella affatto i dati del
+ file, ma si limita a eliminare la relativa voce da una directory e
+ decrementare il numero di riferimenti nell'\textit{inode}.
+
+\item Il numero di \textit{inode} nella voce si riferisce ad un \textit{inode}
+ nello stesso filesystem e non ci può essere una directory che contiene
+ riferimenti ad \textit{inodes} relativi ad altri filesystem. Questo limita
+ l'uso del comando \texttt{ln} (che crea una nuova voce per un file
+ esistente, con la funzione \texttt{link}) al filesystem corrente.
+
+\item Quando si cambia nome ad un file senza cambiare filesystem il contenuto
+ del file non deve essere spostato, viene semplicemente creata una nuova voce
+ per l'\textit{inode} in questione e rimossa la vecchia (questa è la modalità
+ in cui opera normalmente il comando \texttt{mv} attraverso la funzione
+ \texttt{rename}).
+
+\end{enumerate}
+
+Infine è bene avere presente che essendo file pure loro, esiste un numero di
+riferimenti anche per le directories; per cui se ad esempio a partire dalla
+situazione mostrata in \curfig\ creiamo una nuova directory \texttt{textdir}
+nella directory corrente avremo una situazione come quella in \nfig, dove per
+chiarezza abbiamo aggiunto dei numeri di inode.
+
+La nuova directory avrà allora un numero di riferimenti pari a due, in quanto
+è referenziata dalla directory da cui si era partiti (in cui è inserita la
+nuova voce che fa riferimento a \texttt{textdir}) e dalla voce \texttt{.}
+che è sempre inserita in ogni directory; questo vale sempre per ogni directory
+che non contenga a sua volta altre directories. Al contempo la directory da
+cui si era partiti avrà un numero di riferiementi di almeno tre, in quanto
+adesso sarà referenziata anche dalla voce \texttt{..} di \texttt{textdir}.
+
+
+\subsection{Le funzioni \texttt{link} e \texttt{unlink}}
+\label{sec:filedir_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:filedir_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:filedir_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:filedir_cre_canc}
+
+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:filedir_sym_link}
+
+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}
+
+