-\chapter{I files: l'interfaccia I/O di unix}
+\chapter{I file: l'interfaccia standard Unix}
\label{cha:file_unix_interface}
+Esamineremo in questo capitolo la prima delle due interfacce di programmazione
+per i file, quella dei \textit{file descriptor}\index{file descriptor},
+nativa di Unix. Questa è l'interfaccia di basso livello provvista direttamente
+dalle system call, che non prevede funzionalità evolute come la
+bufferizzazione o funzioni di lettura o scrittura formattata, e sulla quale è
+costruita anche l'interfaccia definita dallo standard ANSI C che affronteremo
+al \capref{cha:files_std_interface}.
+
+
+
+\section{L'architettura di base}
+\label{sec:file_base_arch}
+
+In questa sezione faremo una breve introduzione sull'architettura su cui è
+basata dell'interfaccia dei \textit{file descriptor}, che, sia pure con
+differenze nella realizzazione pratica, resta sostanzialmente la stessa in
+tutte le implementazione di un sistema unix-like.
+
+
+\subsection{L'architettura dei \textit{file descriptor}}
+\label{sec:file_fd}
+
+Per poter accedere al contenuto di un file occorre creare un canale di
+comunicazione con il kernel che renda possibile operare su di esso (si ricordi
+quanto visto in \secref{sec:file_vfs_work}). Questo si fa aprendo il file con
+la funzione \func{open} che provvederà a localizzare l'inode del file e
+inizializzare i puntatori che rendono disponibili le funzioni che il VFS mette
+a disposizione (riportate in \tabref{tab:file_file_operations}). Una volta
+terminate le operazioni, il file dovrà essere chiuso, e questo chiuderà il
+canale di comunicazione impedendo ogni ulteriore operazione.
+
+All'interno di ogni processo i file aperti sono identificati da un intero non
+negativo, chiamato appunto \textit{file descriptor}\index{file descriptor}.
+Quando un file viene aperto la funzione \func{open} restituisce questo numero,
+tutte le ulteriori operazioni saranno compiute specificando questo stesso
+valore come argomento alle varie funzioni dell'interfaccia.
+
+Per capire come funziona il meccanismo occorre spiegare a grandi linee come è
+che il kernel gestisce l'interazione fra processi e file. Il kernel mantiene
+sempre un elenco dei processi attivi nella cosiddetta \textit{process table}
+ed un elenco dei file aperti nella \textit{file table}.
+
+La \textit{process table} è una tabella che contiene una voce per ciascun
+processo attivo nel sistema. In Linux ciascuna voce è costituita da una
+struttura di tipo \var{task\_struct} nella quale sono raccolte tutte le
+informazioni relative al processo; fra queste informazioni c'è anche il
+puntatore ad una ulteriore struttura di tipo \var{files\_struct}, in cui sono
+contenute le informazioni relative ai file che il processo ha aperto, ed in
+particolare:
+\begin{itemize*}
+\item i flag relativi ai file descriptor.
+\item il numero di file aperti.
+\item una tabella che contiene un puntatore alla relativa voce nella
+ \textit{file table} per ogni file aperto.
+\end{itemize*}
+il \textit{file descriptor}\index{file descriptor} in sostanza è l'intero
+positivo che indicizza quest'ultima tabella.
+
+La \textit{file table} è una tabella che contiene una voce per ciascun file
+che è stato aperto nel sistema. In Linux è costituita da strutture di tipo
+\var{file}; in ciascuna di esse sono tenute varie informazioni relative al
+file, fra cui:
+\begin{itemize*}
+\item lo stato del file (nel campo \var{f\_flags}).
+\item il valore della posizione corrente (l'\textit{offset}) nel file (nel
+ campo \var{f\_pos}).
+\item un puntatore all'inode\footnote{nel kernel 2.4.x si è in realtà passati
+ ad un puntatore ad una struttura \var{dentry} che punta a sua volta
+ all'inode passando per la nuova struttura del VFS.} del file.
+%\item un puntatore alla tabella delle funzioni \footnote{la struttura
+% \var{f\_op} descritta in \secref{sec:file_vfs_work}} che si possono usare
+% sul file.
+\end{itemize*}
+
+In \figref{fig:file_proc_file} si è riportato uno schema in cui è illustrata
+questa architettura, ed in cui si sono evidenziate le interrelazioni fra le
+varie strutture di dati sulla quale essa è basata.
+\begin{figure}[htb]
+ \centering
+ \includegraphics[width=13cm]{img/procfile}
+ \caption{Schema della architettura dell'accesso ai file attraverso
+ l'interfaccia dei \textit{file descriptor}.}
+ \label{fig:file_proc_file}
+\end{figure}
+Ritorneremo su questo schema più volte, dato che esso è fondamentale per
+capire i dettagli del funzionamento dell'interfaccia dei \textit{file
+ descriptor}\index{file descriptor}.
+
+
+\subsection{I file standard}
+\label{sec:file_std_descr}
+
+Come accennato i \textit{file descriptor}\index{file descriptor} non sono
+altro che un indice nella tabella dei file aperti di ciascun processo; per
+questo motivo essi vengono assegnati in successione tutte le volte che si apre
+un nuovo file (se non ne è stato chiuso nessuno in precedenza).
+
+In tutti i sistemi unix-like esiste una convenzione generale per cui ogni
+processo viene lanciato con almeno tre file aperti. Questi, per quanto appena
+detto, avranno come \textit{file descriptor}\index{file descriptor} i valori
+0, 1 e 2. Benché questa sia soltanto una convenzione, essa è seguita dalla
+gran parte delle applicazioni, e non aderirvi potrebbe portare a gravi
+problemi di interoperabilità.
+
+Il primo file è sempre associato a quello che viene chiamato \textit{standard
+ input}. È cioè il file da cui il processo si aspetta di ricevere i dati in
+ingresso (nel caso della shell, è associato all'ingresso dal terminale, e
+quindi alla lettura della tastiera). Il secondo file è il cosiddetto
+\textit{standard output}, cioè il file su cui ci si aspetta debbano essere
+inviati i dati in uscita (sempre nel caso della shell, è associato all'uscita
+del terminale, e quindi alla scrittura sullo schermo). Il terzo è lo
+\textit{standard error}, su cui viene inviato l'output relativo agli errori,
+ed è anch'esso associato all'uscita del termininale. Lo standard POSIX.1
+provvede tre costanti simboliche, definite nell'header \file{unistd.h}, al
+posto di questi valori numerici:
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|l|}
+ \hline
+ \textbf{Costante} & \textbf{Significato} \\
+ \hline
+ \hline
+ \macro{STDIN\_FILENO} & \textit{file descriptor} dello \textit{standard
+ input} \\
+ \macro{STDOUT\_FILENO} & \textit{file descriptor} dello \textit{standard
+ output} \\
+ \macro{STDERR\_FILENO} & \textit{file descriptor} dello \textit{standard
+ error}\\
+ \hline
+ \end{tabular}
+ \caption{Costanti definite in \file{unistd.h} per i file standard aperti
+ alla creazione di ogni processo.}
+ \label{tab:file_std_files}
+\end{table}
+
+In \figref{tab:file_std_files} si è utilizzata questa situazione come esempio,
+facendo riferimento ad un programma in cui lo \textit{standard input} è
+associato ad un file mentre lo \textit{standard output} e lo \textit{standard
+ error} sono entrambi associati ad un altro file (e quindi utilizzano lo
+stesso inode).
+
+Nelle vecchie versioni di Unix (ed anche in Linux fino al kernel 2.0.x) il
+numero di file aperti era anche soggetto ad un limite massimo dato dalle
+dimensioni del vettore di puntatori con cui era realizzata la tabella dei file
+descriptor dentro \var{file\_struct}; questo limite intrinseco nei kernel più
+recenti non sussiste più, dato che si è passati da un vettore ad una lista, ma
+restano i limiti imposti dall'amministratore (vedi \secref{sec:sys_limits}).
-\section{I file descriptors}
-\label{sec:fileunix_fd}
\section{Le funzioni base}
-\label{sec:fileunix_base_func}
+\label{sec:file_base_func}
+
+L'interfaccia standard Unix per l'input/output sui file è basata su cinque
+funzioni fondamentali: \func{open}, \func{read}, \func{write}, \func{lseek} e
+\func{close}, usate rispettivamente per aprire, leggere, scrivere, spostarsi e
+chiudere un file.
+
+La gran parte delle operazioni sui file si effettua attraverso queste cinque
+funzioni, esse vengono chiamate anche funzioni di I/O non bufferizzato dato
+che effettuano le operazioni di lettura e scrittura usando direttamente le
+system call del kernel.
+
+
+\subsection{La funzione \func{open}}
+\label{sec:file_open}
+
+La funzione \func{open} è la funzione fondamentale per accedere ai file, ed è
+quella che crea l'associazione fra un pathname ed un file descriptor, il suo
+prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/stat.h}
+ \headdecl{fcntl.h}
+ \funcdecl{int open(const char *pathname, int flags)}
+ \funcdecl{int open(const char *pathname, int flags, mode\_t mode)}
+ Apre il file indicato da \var{pathname} nella modalità indicata da
+ \var{flags}, e, nel caso il file sia creato, con gli eventuali permessi
+ specificati da \var{mode}.
+
+ \bodydesc{La funzione ritorna il file descriptor in caso di successo e -1 in
+ caso di errore. In questo caso la variabile \var{errno} assumerà uno dei
+ valori:
+ \begin{errlist}
+ \item[\macro{EEXIST}] \var{pathname} esiste e si è specificato
+ \macro{O\_CREAT} e \macro{O\_EXCL}.
+ \item[\macro{EISDIR}] \var{pathname} indica una directory e si è tentato
+ l'accesso in scrittura.
+ \item[\macro{ENOTDIR}] si è specificato \macro{O\_DIRECTORY} e \var{pathname}
+ non è una directory.
+ \item[\macro{ENXIO}] si sono impostati \macro{O\_NOBLOCK} o \macro{O\_WRONLY}
+ ed il file è una fifo che non viene letta da nessun processo o
+ \var{pathname} è un file di dispositivo ma il dispositivo è assente.
+ \item[\macro{ENODEV}] \var{pathname} si riferisce a un file di dispositivo
+ che non esiste.
+ \item[\macro{ETXTBSY}] si è cercato di accedere in scrittura all'immagine di
+ un programma in esecuzione.
+ \item[\macro{ELOOP}] si sono incontrati troppi link simbolici nel risolvere
+ pathname o si è indicato \macro{O\_NOFOLLOW} e \var{pathname} è un link
+ simbolico.
+ \end{errlist}
+ ed inoltre \macro{EACCES}, \macro{ENAMETOOLONG}, \macro{ENOENT},
+ \macro{EROFS}, \macro{EFAULT}, \macro{ENOSPC}, \macro{ENOMEM},
+ \macro{EMFILE} e \macro{ENFILE}.}
+\end{functions}
+
+La funzione apre il file, usando il primo file descriptor libero, e crea
+l'opportuna voce (cioè la struttura \var{file}) nella file table. Viene usato
+sempre il file descriptor con il valore più basso.
+
+\begin{table}[!htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{12cm}|}
+ \hline
+ \textbf{Flag} & \textbf{Descrizione} \\
+ \hline
+ \hline % modalità di accesso al file
+ \macro{O\_RDONLY} & apre il file in sola lettura. \\
+ \macro{O\_WRONLY} & apre il file in sola scrittura. \\
+ \macro{O\_RDWR} & apre il file in lettura/scrittura. \\
+ \hline % modalità di apertura del file
+ \hline
+ \macro{O\_CREAT} & se il file non esiste verrà creato, con le regole di
+ titolarità del file viste in \secref{sec:file_ownership}. Il parametro
+ \var{mode} deve essere specificato. \\
+ \macro{O\_EXCL} & usato in congiunzione con \macro{O\_CREAT} fa sì che
+ l'esistenza del file diventi un errore\protect\footnotemark\ che fa fallire
+ \func{open} con \macro{EEXIST}. \\
+ \macro{O\_NONBLOCK} & apre il file in modalità non bloccante. Questo
+ valore specifica anche una modalità di operazione (vedi sotto), e
+ comporta che \func{open} ritorni immediatamente (l'opzione ha senso
+ solo per le fifo, torneremo questo in \secref{sec:ipc_named_pipe}). \\
+ \macro{O\_NOCTTY} & se \var{pathname} si riferisce ad un device di
+ terminale, questo non diventerà il terminale di controllo, anche se il
+ processo non ne ha ancora uno (si veda \secref{sec:sess_ctrl_term}). \\
+ \macro{O\_SHLOCK} & opzione di BSD, acquisisce uno shared lock (vedi
+ \secref{sec:file_locking}) sul file. Non è disponibile in Linux. \\
+ \macro{O\_EXLOCK} & opzione di BSD, acquisisce uno lock esclusivo (vedi
+ \secref{sec:file_locking}) sul file. Non è disponibile in Linux. \\
+ \macro{O\_TRUNC} & se il file esiste ed è un file di dati e la modalità di
+ apertura consente la scrittura, allora la sua lunghezza verrà troncata a
+ zero. Se il file è un terminale o una fifo il flag verrà ignorato, negli
+ altri casi il comportamento non è specificato. \\
+ \macro{O\_NOFOLLOW} & se \var{pathname} è un link simbolico la chiamata
+ fallisce. Questa è un'estensione BSD aggiunta in Linux dal kernel 2.1.126.
+ Nelle versioni precedenti i link simbolici sono sempre seguiti, e questa
+ opzione è ignorata. \\
+ \macro{O\_DIRECTORY} & se \var{pathname} non è una directory la chiamata
+ fallisce. Questo flag è specifico di Linux ed è stato introdotto con il
+ kernel 2.1.126 per evitare dei
+ \textit{DoS}\index{DoS}\protect\footnotemark\ quando
+ \func{opendir} viene chiamata su una
+ fifo o su un device di unità a nastri, non deve essere utilizzato al di
+ fuori dell'implementazione di \func{opendir}. \\
+ \macro{O\_LARGEFILE} & nel caso di sistemi a 32 bit che supportano file di
+ grandi dimensioni consente di aprire file le cui dimensioni non possono
+ essere rappresentate da numeri a 31 bit. \\
+ \hline
+ \hline % modalità di operazione col file
+ \macro{O\_APPEND} & il file viene aperto in append mode. Prima di ciascuna
+ scrittura la posizione corrente viene sempre impostata alla fine del
+ file. Può causare corruzione del file con NFS se più di un processo scrive
+ allo stesso tempo.\footnotemark\\
+ \macro{O\_NONBLOCK} & il file viene aperto in modalità non bloccante per
+ le operazioni di I/O (che tratteremo in \secref{sec:file_noblocking}):
+ questo significa il fallimento di \func{read} in assenza di dati da
+ leggere e quello di \func{write} in caso di impossibilità di scrivere
+ immediatamente. Questa modalità ha senso solo per le fifo e per alcuni
+ file di dispositivo. \\
+ \macro{O\_NDELAY} & in Linux\footnotemark\ è sinonimo di
+ \macro{O\_NONBLOCK}.\\
+ \macro{O\_ASYNC} & apre il file per l'I/O in modalità
+ asincrona (vedi \secref{sec:file_asyncronous_io}). Quando è impostato viene
+ generato il segnale \macro{SIGIO} tutte le volte che sono disponibili
+ dati in input sul file. \\
+ \macro{O\_SYNC} & apre il file per l'input/output sincrono, ogni
+ \func{write} bloccherà fino al completamento della scrittura di tutti dati
+ sul sull'hardware sottostante.\\
+ \macro{O\_FSYNC} & sinonimo di \macro{O\_SYNC}. \\
+ \macro{O\_NOATIME} & blocca l'aggiornamento dei tempi dei di accesso dei
+ file (vedi \secref{sec:file_file_times}). In Linux questa opzione non è
+ disponibile per il singolo file ma come opzione per il filesystem in fase
+ di montaggio.\\
+ \hline
+ \end{tabular}
+ \caption{Valori e significato dei vari bit del \textit{file status flag}.}
+ \label{tab:file_open_flags}
+\end{table}
+
+\footnotetext[2]{la pagina di manuale di \func{open} segnala che questa
+ opzione è difettosa su NFS, e che i programmi che la usano per stabilire un
+ file di lock (vedi \secref{sec:ipc_file_lock}) possono incorrere in una race
+ condition\index{race condition}. Si consiglia come alternativa di usare un
+ file con un nome univoco e la funzione \func{link} per verificarne
+ l'esistenza.}
+
+\footnotetext[3]{\textit{Denial of Service}, si chiamano così attacchi miranti
+ ad impedire un servizio causando una qualche forma di carico eccessivo per
+ il sistema, che resta bloccato nelle risposte all'attacco.}
+
+\footnotetext[4]{il problema è che NFS non supporta la scrittura in append, ed
+ il kernel deve simularla, ma questo comporta la possibilità di una race
+ condition, vedi \secref{sec:file_atomic}.}
+
+\footnotetext[5]{l'opzione origina da SVr4, dove però causava il ritorno da
+ una \func{read} con un valore nullo e non con un errore, questo introduce
+ un'ambiguità, dato che come vedremo in \secref{sec:file_read} il ritorno di
+ zero da parte di \func{read} ha il significato di una end-of-file.}
+
+Questa caratteristica permette di prevedere qual'è il valore del file
+descriptor che si otterrà al ritorno di \func{open}, e viene talvolta usata da
+alcune applicazioni per sostituire i file corrispondenti ai file standard
+visti in \secref{sec:file_std_descr}: se ad esempio si chiude lo standard
+input e si apre subito dopo un nuovo file questo diventerà il nuovo standard
+input (avrà cioè il file descriptor 0).
+
+Il nuovo file descriptor non è condiviso con nessun altro processo (torneremo
+sulla condivisione dei file, in genere accessibile dopo una \func{fork}, in
+\secref{sec:file_sharing}). Il nuovo file descriptor è impostato per restare
+aperto attraverso una \func{exec} (come accennato in \secref{sec:proc_exec}) e
+l'offset è impostato all'inizio del file.
+
+L'argomento \param{mode} specifica i permessi con cui il file viene
+eventualmente creato; i valori possibili sono gli stessi già visti in
+\secref{sec:file_perm_overview} e possono essere specificati come OR binario
+delle costanti descritte in \tabref{tab:file_bit_perm}. Questi permessi sono
+filtrati dal valore di \var{umask} (vedi \secref{sec:file_umask}) per il
+processo.
+
+La funzione prevede diverse opzioni, che vengono specificate usando vari bit
+dell'argomento \param{flags}. Alcuni di questi bit vanno anche a costituire
+il flag di stato del file (o \textit{file status flag}), che è mantenuto nel
+campo \var{f\_flags} della struttura \var{file} (al solito si veda lo schema
+di \figref{fig:file_proc_file}). Essi sono divisi in tre categorie
+principali:
+\begin{itemize}
+\item \textsl{i bit delle modalità di accesso}: specificano con quale modalità
+ si accederà al file: i valori possibili sono lettura, scrittura o
+ lettura/scrittura. Uno di questi bit deve essere sempre specificato quando
+ si apre un file. Vengono impostati alla chiamata da \func{open}, e possono
+ essere riletti con una \func{fcntl} (fanno parte del \textit{file status
+ flag}), ma non possono essere modificati.
+\item \textsl{i bit delle modalità di apertura}: permettono di specificare
+ alcune delle caratteristiche del comportamento di \func{open} quando viene
+ eseguita. Hanno effetto solo al momento della chiamata della funzione e non
+ sono memorizzati né possono essere riletti.
+\item \textsl{i bit delle modalità di operazione}: permettono di specificare
+ alcune caratteristiche del comportamento delle future operazioni sul file
+ (come la \func{read} o la \func{write}). Anch'essi fanno parte del
+ \textit{file status flag}. Il loro valore è impostato alla chiamata di
+ \func{open}, ma possono essere riletti e modificati (insieme alle
+ caratteristiche operative che controllano) con una \func{fcntl}.
+\end{itemize}
+
+In \tabref{tab:file_open_flags} si sono riportate, ordinate e divise fra loro
+secondo le tre modalità appena elencate, le costanti mnemoniche associate a
+ciascuno di questi bit. Dette costanti possono essere combinate fra di loro
+con un OR aritmetico per costruire il valore (in forma di maschera binaria)
+dell'argomento \param{flags} da passare alla \func{open} per specificarne il
+comportamento. I due flag \macro{O\_NOFOLLOW} e \macro{O\_DIRECTORY} sono
+estensioni specifiche di Linux, e deve essere definita la macro
+\macro{\_GNU\_SOURCE} per poterli usare.
+
+Nelle prime versioni di Unix i valori di \param{flag} specificabili per
+\func{open} erano solo quelli relativi alle modalità di accesso del file. Per
+questo motivo per creare un nuovo file c'era una system call apposita,
+\func{creat}, il cui prototipo è:
+\begin{prototype}{fcntl.h}
+ {int creat(const char *pathname, mode\_t mode)}
+ Crea un nuovo file vuoto, con i permessi specificati da \var{mode}. È del
+ tutto equivalente a \code{open(filedes, O\_CREAT|O\_WRONLY|O\_TRUNC, mode)}.
+\end{prototype}
+\noindent adesso questa funzione resta solo per compatibilità con i vecchi
+programmi.
+
+
+\subsection{La funzione \func{close}}
+\label{sec:file_close}
+
+La funzione \func{close} permette di chiudere un file, in questo modo il file
+descriptor ritorna disponibile; il suo prototipo è:
+\begin{prototype}{unistd.h}{int close(int fd)}
+ Chiude il descrittore \var{fd}.
+
+ \bodydesc{La funzione ritorna 0 in caso di successo e -1 in caso di errore,
+ ed in questo caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\macro{EBADF}] \var{fd} non è un descrittore valido.
+ \item[\macro{EINTR}] la funzione è stata interrotta da un segnale.
+ \end{errlist}
+ ed inoltre \macro{EIO}.}
+\end{prototype}
+
+La chiusura di un file rilascia ogni blocco (il \textit{file locking} è
+trattato in \secref{sec:file_locking}) che il processo poteva avere acquisito
+su di esso; se \var{fd} è l'ultimo riferimento (di eventuali copie) ad un file
+aperto, tutte le risorse nella file table vengono rilasciate. Infine se il
+file descriptor era l'ultimo riferimento ad un file su disco quest'ultimo
+viene cancellato.
+
+Si ricordi che quando un processo termina anche tutti i suoi file descriptor
+vengono chiusi, molti programmi sfruttano questa caratteristica e non usano
+esplicitamente \func{close}. In genere comunque chiudere un file senza
+controllarne lo stato di uscita è errore; infatti molti filesystem
+implementano la tecnica del \textit{write-behind}, per cui una \func{write}
+può avere successo anche se i dati non sono stati scritti, un eventuale errore
+di I/O allora può sfuggire, ma verrà riportato alla chiusura del file: per
+questo motivo non effettuare il controllo può portare ad una perdita di dati
+inavvertita.\footnote{in Linux questo comportamento è stato osservato con NFS
+ e le quote su disco.}
+
+In ogni caso una \func{close} andata a buon fine non garantisce che i dati
+siano stati effettivamente scritti su disco, perché il kernel può decidere di
+ottimizzare l'accesso a disco ritardandone la scrittura. L'uso della funzione
+\func{sync} (vedi \secref{sec:file_sync}) effettua esplicitamente il
+\emph{flush} dei dati, ma anche in questo caso resta l'incertezza dovuta al
+comportamento dell'hardware (che a sua volta può introdurre ottimizzazioni
+dell'accesso al disco che ritardano la scrittura dei dati, da cui l'abitudine
+di ripetere tre volte il comando prima di eseguire lo shutdown).
+
+
+\subsection{La funzione \func{lseek}}
+\label{sec:file_lseek}
+
+Come già accennato in \secref{sec:file_fd} a ciascun file aperto è associata
+una \textsl{posizione corrente nel file} (il cosiddetto \textit{file offset},
+mantenuto nel campo \var{f\_pos} di \var{file}) espressa da un numero intero
+positivo come numero di byte dall'inizio del file. Tutte le operazioni di
+lettura e scrittura avvengono a partire da questa posizione che viene
+automaticamente spostata in avanti del numero di byte letti o scritti.
+
+In genere (a meno di non avere richiesto la modalità \macro{O\_APPEND}) questa
+posizione viene impostata a zero all'apertura del file. È possibile impostarla
+ad un valore qualsiasi con la funzione \func{lseek}, il cui prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{unistd.h}
+ \funcdecl{off\_t lseek(int fd, off\_t offset, int whence)}
+ Imposta la posizione attuale nel file.
+
+ \bodydesc{La funzione ritorna valore della posizione corrente in caso di
+ successo e -1 in caso di errore nel qual caso \var{errno} assumerà uno dei
+ valori:
+ \begin{errlist}
+ \item[\macro{ESPIPE}] \param{fd} è una pipe, un socket o una fifo.
+ \item[\macro{EINVAL}] \param{whence} non è un valore valido.
+ \end{errlist}
+ ed inoltre \macro{EBADF}.}
+\end{functions}
+
+La nuova posizione è impostata usando il valore specificato da \param{offset},
+sommato al riferimento dato da \param{whence}; quest'ultimo può assumere i
+seguenti valori\footnote{per compatibilità con alcune vecchie notazioni
+ questi valori possono essere rimpiazzati rispettivamente con 0, 1 e 2 o con
+ \macro{L\_SET}, \macro{L\_INCR} e \macro{L\_XTND}.}:
+\begin{basedescript}{\desclabelwidth{2.0cm}}
+\item[\macro{SEEK\_SET}] si fa riferimento all'inizio del file: il valore
+ (sempre positivo) di \param{offset} indica direttamente la nuova posizione
+ corrente.
+\item[\macro{SEEK\_CUR}] si fa riferimento alla posizione corrente del file:
+ ad essa viene sommato \param{offset} (che può essere negativo e positivo)
+ per ottenere la nuova posizione corrente.
+\item[\macro{SEEK\_END}] si fa riferimento alla fine del file: alle dimensioni
+ del file viene sommato \param{offset} (che può essere negativo e positivo)
+ per ottenere la nuova posizione corrente.
+\end{basedescript}
+
+Come accennato in \secref{sec:file_file_size} con \func{lseek} è possibile
+impostare la posizione corrente anche oltre la fine del file, e alla
+successiva scrittura il file sarà esteso. La chiamata non causa nessuna
+attività di input/output, si limita a modificare la posizione corrente nel
+kernel (cioè \var{f\_pos} in \var{file}, vedi \figref{fig:file_proc_file}).
+
+Dato che la funzione ritorna la nuova posizione, usando il valore zero per
+\param{offset} si può riottenere la posizione corrente nel file chiamando la
+funzione con \code{lseek(fd, 0, SEEK\_CUR)}.
+
+Si tenga presente inoltre che usare \macro{SEEK\_END} non assicura affatto che
+la successiva scrittura avvenga alla fine del file, infatti se questo è stato
+aperto anche da un altro processo che vi ha scritto, la fine del file può
+essersi spostata, ma noi scriveremo alla posizione impostata in precedenza
+(questa è una potenziale sorgente di \textit{race condition}\index{race
+ condition}, vedi \secref{sec:file_atomic}).
+
+Non tutti i file supportano la capacità di eseguire una \func{lseek}, in
+questo caso la funzione ritorna l'errore \macro{EPIPE}. Questo, oltre che per
+i tre casi citati nel prototipo, vale anche per tutti quei dispositivi che non
+supportano questa funzione, come ad esempio per i file di
+terminale.\footnote{altri sistemi, usando \macro{SEEK\_SET}, in questo caso
+ ritornano il numero di caratteri che vi sono stati scritti.} Lo standard
+POSIX però non specifica niente in proposito. Infine alcuni file speciali, ad
+esempio \file{/dev/null}, non causano un errore ma restituiscono un valore
+indefinito.
+
+
+\subsection{La funzione \func{read}}
+\label{sec:file_read}
+
+
+Una volta che un file è stato aperto (con il permesso in lettura) su possono
+leggere i dati che contiene utilizzando la funzione \func{read}, il cui
+prototipo è:
+\begin{prototype}{unistd.h}{ssize\_t read(int fd, void * buf, size\_t count)}
+
+ Cerca di leggere \var{count} byte dal file \var{fd} al buffer \var{buf}.
+
+ \bodydesc{La funzione ritorna il numero di byte letti in caso di successo e
+ -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\macro{EINTR}] la funzione è stata interrotta da un segnale prima di
+ aver potuto leggere qualsiasi dato.
+ \item[\macro{EAGAIN}] la funzione non aveva nessun dato da restituire e si
+ era aperto il file in modalità \macro{O\_NONBLOCK}.
+ \end{errlist}
+ ed inoltre \macro{EBADF}, \macro{EIO}, \macro{EISDIR}, \macro{EBADF},
+ \macro{EINVAL} e \macro{EFAULT} ed eventuali altri errori dipendenti dalla
+ natura dell'oggetto connesso a \var{fd}.}
+\end{prototype}
+
+La funzione tenta di leggere \var{count} byte a partire dalla posizione
+corrente nel file. Dopo la lettura la posizione sul file è spostata
+automaticamente in avanti del numero di byte letti. Se \var{count} è zero la
+funzione restituisce zero senza nessun altro risultato.
+
+Si deve sempre tener presente che non è detto che la funzione \func{read}
+restituisca sempre il numero di byte richiesto, ci sono infatti varie ragioni
+per cui la funzione può restituire un numero di byte inferiore; questo è un
+comportamento normale, e non un errore, che bisogna sempre tenere presente.
+
+La prima e più ovvia di queste ragioni è che si è chiesto di leggere più byte
+di quanto il file ne contenga. In questo caso il file viene letto fino alla
+sua fine, e la funzione ritorna regolarmente il numero di byte letti
+effettivamente.
+
+Raggiunta la fine del file, alla ripetizione di un'operazione di lettura,
+otterremmo il ritorno immediato di \func{read} con uno zero. La condizione di
+raggiungimento della fine del file non è un errore, e viene segnalata appunto
+da un valore di ritorno di \func{read} nullo. Ripetere ulteriormente la
+lettura non avrebbe nessun effetto se non quello di continuare a ricevere zero
+come valore di ritorno.
+
+Con i \textsl{file regolari} questa è l'unica situazione in cui si può avere
+un numero di byte letti inferiore a quello richiesto, ma questo non è vero
+quando si legge da un terminale, da una fifo o da una pipe. In tal caso
+infatti, se non ci sono dati in ingresso, la \func{read} si blocca (a meno di
+non aver selezionato la modalità non bloccante, vedi
+\secref{sec:file_noblocking}) e ritorna solo quando ne arrivano; se il numero
+di byte richiesti eccede quelli disponibili la funzione ritorna comunque, ma
+con un numero di byte inferiore a quelli richiesti.
+
+Lo stesso comportamento avviene caso di lettura dalla rete (cioè su un socket,
+come vedremo in \secref{sec:sock_io_behav}), o per la lettura da certi file di
+dispositivo, come le unità a nastro, che restituiscono sempre i dati ad un
+singolo blocco alla volta.
+
+In realtà anche le due condizioni segnalate dagli errori \macro{EINTR} e
+\macro{EAGAIN} non sono errori. La prima si verifica quando la \func{read} è
+bloccata in attesa di dati in ingresso e viene interrotta da un segnale; in
+tal caso l'azione da intraprendere è quella di rieseguire la funzione.
+Torneremo in dettaglio sull'argomento in \secref{sec:sig_gen_beha}.
+
+La seconda si verifica quando il file è in modalità non bloccante (vedi
+\secref{sec:file_noblocking}) e non ci sono dati in ingresso: la funzione
+allora ritorna immediatamente con un errore \macro{EAGAIN}\footnote{sotto BSD
+ per questo errore viene usata la costante \macro{EWOULDBLOCK}, in Linux, con
+ le glibc, questa è sinonima di \macro{EAGAIN}.} che indica soltanto che
+occorrerà provare a ripetere la lettura.
+
+La funzione \func{read} è una delle system call fondamentali, esistenti fin
+dagli albori di Unix, ma nella seconda versione delle \textit{Single Unix
+ Specification}\footnote{questa funzione, e l'analoga \func{pwrite} sono
+ state aggiunte nel kernel 2.1.60, il supporto nelle \acr{glibc}, compresa
+ l'emulazione per i vecchi kernel che non hanno la system call, è stato
+ aggiunto con la versione 2.1, in versioni precedenti sia del kernel che
+ delle librerie la funzione non è disponibile.} (quello che viene chiamato
+normalmente Unix98, vedi \secref{sec:intro_opengroup}) è stata introdotta la
+definizione di un'altra funzione di lettura, \func{pread}, il cui prototipo è:
+\begin{prototype}{unistd.h}
+{ssize\_t pread(int fd, void * buf, size\_t count, off\_t offset)}
+
+Cerca di leggere \var{count} byte dal file \var{fd}, a partire dalla posizione
+\var{offset}, nel buffer \var{buf}.
+
+\bodydesc{La funzione ritorna il numero di byte letti in caso di successo e -1
+ in caso di errore, nel qual caso \var{errno} assumerà i valori già visti per
+ \func{read} e \func{lseek}.}
+\end{prototype}
+\noindent che però diventa accessibile solo con la definizione della macro:
+\begin{verbatim}
+ #define _XOPEN_SOURCE 500
+\end{verbatim}
+
+Questa funzione serve quando si vogliono leggere dati dal file senza
+modificare la posizione corrente. È equivalente all'esecuzione di una
+\func{read} seguita da una \func{lseek} che riporti al valore precedente la
+posizione corrente sul file, ma permette di eseguire l'operazione
+atomicamente. Questo può essere importante quando la posizione sul file viene
+condivisa da processi diversi (vedi \secref{sec:file_sharing}). Il valore di
+\var{offset} fa sempre riferimento all'inizio del file.
+
+
+\subsection{La funzione \func{write}}
+\label{sec:file_write}
+
+Una volta che un file è stato aperto (con il permesso in scrittura) su può
+scrivere su di esso utilizzando la funzione \func{write}, il cui prototipo è:
+\begin{prototype}{unistd.h}{ssize\_t write(int fd, void * buf, size\_t count)}
+
+ Scrive \var{count} byte dal buffer \var{buf} sul file \var{fd}.
+
+ \bodydesc{La funzione ritorna il numero di byte scritti in caso di successo
+ e -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\macro{EINVAL}] \var{fd} è connesso ad un oggetto che non consente la
+ scrittura.
+ \item[\macro{EFBIG}] si è cercato di scrivere oltre la dimensione massima
+ consentita dal filesystem o il limite per le dimensioni dei file del
+ processo o su una posizione oltre il massimo consentito.
+ \item[\macro{EPIPE}] \var{fd} è connesso ad una pipe il cui altro capo è
+ chiuso in lettura; in questo caso viene anche generato il segnale
+ \macro{SIGPIPE}, se questo viene gestito (o bloccato o ignorato) la
+ funzione ritorna questo errore.
+ \item[\macro{EINTR}] la funzione è stata interrotta da un segnale prima di
+ aver potuto scrivere qualsiasi dato.
+ \item[\macro{EAGAIN}] la funzione non aveva nessun dato da restituire e si
+ era aperto il file in modalità \macro{O\_NONBLOCK}.
+ \end{errlist}
+ ed inoltre \macro{EBADF}, \macro{EIO}, \macro{EISDIR}, \macro{EBADF},
+ \macro{ENOSPC}, \macro{EINVAL} e \macro{EFAULT} ed eventuali altri errori
+ dipendenti dalla natura dell'oggetto connesso a \var{fd}.}
+\end{prototype}
+
+Come nel caso di \func{read} la funzione tenta di scrivere \var{count} byte a
+partire dalla posizione corrente nel file e sposta automaticamente la
+posizione in avanti del numero di byte scritti. Se il file è aperto in
+modalità \macro{O\_APPEND} i dati vengono sempre scritti alla fine del file.
+Lo standard POSIX richiede che i dati scritti siano immediatamente disponibili
+ad una \func{read} chiamata dopo che la \func{write} che li ha scritti è
+ritornata; ma dati i meccanismi di caching non è detto che tutti i filesystem
+supportino questa capacità.
+
+Se \var{count} è zero la funzione restituisce zero senza fare nient'altro. Per
+i file ordinari il numero di byte scritti è sempre uguale a quello indicato
+da \var{count}, a meno di un errore. Negli altri casi si ha lo stesso
+comportamento di \func{read}.
+
+Anche per \func{write} lo standard Unix98 definisce un'analoga \func{pwrite}
+per scrivere alla posizione indicata senza modificare la posizione corrente
+nel file, il suo prototipo è:
+\begin{prototype}{unistd.h}
+{ssize\_t pwrite(int fd, void * buf, size\_t count, off\_t offset)}
+
+Cerca di scrivere sul file \var{fd}, a partire dalla posizione \var{offset},
+\var{count} byte dal buffer \var{buf}.
+
+\bodydesc{La funzione ritorna il numero di byte letti in caso di successo e -1
+ in caso di errore, nel qual caso \var{errno} assumerà i valori già visti per
+ \func{write} e \func{lseek}.}
+\end{prototype}
+\noindent e per essa valgono le stesse considerazioni fatte per \func{pread}.
+
+
+\section{Caratteristiche avanzate}
+\label{sec:file_adv_func}
+
+In questa sezione approfondiremo alcune delle caratteristiche più sottili
+della gestione file in un sistema unix-like, esaminando in dettaglio il
+comportamento delle funzioni base, inoltre tratteremo le funzioni che
+permettono di eseguire alcune operazioni avanzate con i file (il grosso
+dell'argomento sarà comunque affrontato in \capref{cha:file_advanced}).
+
+
+\subsection{La condivisione dei files}
+\label{sec:file_sharing}
+
+In \secref{sec:file_fd} abbiamo descritto brevemente l'architettura
+dell'interfaccia con i file da parte di un processo, mostrando in
+\figref{fig:file_proc_file} le principali strutture usate dal kernel;
+esamineremo ora in dettaglio le conseguenze che questa architettura ha nei
+confronti dell'accesso allo stesso file da parte di processi diversi.
+
+\begin{figure}[htb]
+ \centering
+ \includegraphics[width=13cm]{img/filemultacc}
+ \caption{Schema dell'accesso allo stesso file da parte di due processi
+ diversi}
+ \label{fig:file_mult_acc}
+\end{figure}
+
+Il primo caso è quello in cui due processi diversi che aprono lo stesso file
+su disco; sulla base di quanto visto in \secref{sec:file_fd} avremo una
+situazione come quella illustrata in \figref{fig:file_mult_acc}: ciascun
+processo avrà una sua voce nella \textit{file table} referenziata da un
+diverso file descriptor nella sua \var{file\_struct}. Entrambe le voci nella
+\textit{file table} faranno però riferimento allo stesso inode su disco.
+
+Questo significa che ciascun processo avrà la sua posizione corrente sul file,
+la sua modalità di accesso e versioni proprie di tutte le proprietà che
+vengono mantenute nella sua voce della \textit{file table}. Questo ha
+conseguenze specifiche sugli effetti della possibile azione simultanea sullo
+stesso file, in particolare occorre tenere presente che:
+\begin{itemize}
+\item ciascun processo può scrivere indipendentemente; dopo ciascuna
+ \func{write} la posizione corrente sarà cambiata solo nel processo. Se la
+ scrittura eccede la dimensione corrente del file questo verrà esteso
+ automaticamente con l'aggiornamento del campo \var{i\_size} nell'inode.
+\item se un file è in modalità \macro{O\_APPEND} tutte le volte che viene
+ effettuata una scrittura la posizione corrente viene prima impostata alla
+ dimensione corrente del file letta dall'inode. Dopo la scrittura il file
+ viene automaticamente esteso.
+\item l'effetto di \func{lseek} è solo quello di cambiare il campo \var{f\_pos}
+ nella struttura \var{file} della \textit{file table}, non c'è nessuna
+ operazione sul file su disco. Quando la si usa per porsi alla fine del file
+ la posizione viene impostata leggendo la dimensione corrente dall'inode.
+\end{itemize}
+
+\begin{figure}[htb]
+ \centering
+ \includegraphics[width=13cm]{img/fileshar}
+ \caption{Schema dell'accesso ai file da parte di un processo figlio}
+ \label{fig:file_acc_child}
+\end{figure}
+
+Il secondo caso è quello in cui due file descriptor di due processi diversi
+puntino alla stessa voce nella \textit{file table}; questo è ad esempio il
+caso dei file aperti che vengono ereditati dal processo figlio all'esecuzione
+di una \func{fork} (si ricordi quanto detto in \secref{sec:proc_fork}). La
+situazione è illustrata in \figref{fig:file_acc_child}; dato che il processo
+figlio riceve una copia dello spazio di indirizzi del padre, riceverà anche
+una copia di \var{file\_struct} e relativa tabella dei file aperti.
+
+In questo modo padre e figlio avranno gli stessi file descriptor che faranno
+riferimento alla stessa voce nella \textit{file table}, condividendo così la
+posizione corrente sul file. Questo ha le conseguenze descritte a suo tempo in
+\secref{sec:proc_fork}: in caso di scrittura contemporanea la posizione
+corrente nel file varierà per entrambi i processi (in quanto verrà modificato
+\var{f\_pos} che è lo stesso per entrambi).
+
+Si noti inoltre che anche i flag di stato del file (quelli impostati
+dall'argomento \param{flag} di \func{open}) essendo tenuti nella voce della
+\textit{file table}\footnote{per la precisione nel campo \var{f\_flags} di
+ \var{file}.}, vengono in questo caso condivisi. Ai file però sono associati
+anche altri flag, dei quali l'unico usato al momento è \macro{FD\_CLOEXEC},
+detti \textit{file descriptor flags}. Questi ultimi sono tenuti invece in
+\var{file\_struct}, e perciò sono specifici di ciascun processo e non vengono
+modificati dalle azioni degli altri anche in caso di condivisione della stessa
+voce della \textit{file table}.
+
+
+
+\subsection{Operazioni atomiche con i file}
+\label{sec:file_atomic}
+
+Come si è visto in un sistema unix-like è sempre possibile per più processi
+accedere in contemporanea allo stesso file, e che le operazioni di lettura e
+scrittura possono essere fatte da ogni processo in maniera autonoma in base
+ad una posizione corrente nel file che è locale a ciascuno di essi.
+
+Se dal punto di vista della lettura dei dati questo non comporta nessun
+problema, quando si andrà a scrivere le operazioni potranno mescolarsi in
+maniera imprevedibile. Il sistema però fornisce in alcuni casi la possibilità
+di eseguire alcune operazioni di scrittura in maniera coordinata anche senza
+utilizzare meccanismi di sincronizzazione più complessi (come il \textit{file
+ locking}, che esamineremo in \secref{cha:file_advanced}).
+
+Un caso tipico di necessità di accesso condiviso in scrittura è quello in cui
+vari processi devono scrivere alla fine di un file (ad esempio un file di
+log). Come accennato in \secref{sec:file_lseek} impostare la posizione alla
+fine del file e poi scrivere può condurre ad una \textit{race
+ condition}\index{race condition}: infatti può succedere che un secondo
+processo scriva alla fine del file fra la \func{lseek} e la \func{write}; in
+questo caso, come abbiamo appena visto, il file sarà esteso, ma il nostro
+primo processo avrà ancora la posizione corrente impostata con la \func{lseek}
+che non corrisponde più alla fine del file, e la successiva \func{write}
+sovrascriverà i dati del secondo processo.
+
+Il problema è che usare due system call in successione non è un'operazione
+atomica; il problema è stato risolto introducendo la modalità
+\macro{O\_APPEND}. In questo caso infatti, come abbiamo descritto in
+precedenza, è il kernel che aggiorna automaticamente la posizione alla fine
+del file prima di effettuare la scrittura, e poi estende il file. Tutto questo
+avviene all'interno di una singola system call (la \func{write}) che non
+essendo interrompibile da un altro processo costituisce un'operazione atomica.
+
+Un altro caso tipico in cui è necessaria l'atomicità è quello in cui si vuole
+creare un file di lock, bloccandosi se il file esiste. In questo caso la
+sequenza logica porterebbe a verificare prima l'esistenza del file con una
+\func{stat} per poi crearlo con una \func{creat}; di nuovo avremmo la
+possibilità di una race condition\index{race condition} da parte di un altro
+processo che crea lo stesso file fra il controllo e la creazione.
+
+Per questo motivo sono stati introdotti per \func{open} i due flag
+\macro{O\_CREAT} e \macro{O\_EXCL}. In questo modo l'operazione di controllo
+dell'esistenza del file (con relativa uscita dalla funzione con un errore) e
+creazione in caso di assenza, diventa atomica essendo svolta tutta all'interno
+di una singola system call.
+
+
+\subsection{La funzioni \func{sync} e \func{fsync}}
+\label{sec:file_sync}
+
+Come accennato in \secref{sec:file_close} tutte le operazioni di scrittura
+sono in genere bufferizzate dal kernel, che provvede ad effettuarle in maniera
+asincrona (ad esempio accorpando gli accessi alla stessa zona del disco) in un
+secondo tempo rispetto al momento della esecuzione della \func{write}.
+
+Per questo motivo, quando è necessaria una sincronizzazione dei dati, il
+sistema mette a disposizione delle funzioni che provvedono a forzare lo
+scarico dei dati dai buffer del kernel.\footnote{come già accennato neanche
+ questo dà la garanzia assoluta che i dati siano integri dopo la chiamata,
+ l'hardware dei dischi è in genere dotato di un suo meccanismo interno di
+ ottimizzazione per l'accesso al disco che può ritardare ulteriormente la
+ scrittura effettiva.} La prima di queste funzioni è \func{sync} il cui
+prototipo è:
+\begin{prototype}{unistd.h}{int sync(void)}
+
+ Sincronizza il buffer della cache dei file col disco.
+
+ \bodydesc{La funzione ritorna sempre zero.}
+\end{prototype}
+\noindent i vari standard prevedono che la funzione si limiti a far partire
+le operazioni, ritornando immediatamente; in Linux (dal kernel 1.3.20) invece
+la funzione aspetta la conclusione delle operazioni di sincronizzazione del
+kernel.
+
+La funzione viene usata dal comando \cmd{sync} quando si vuole forzare
+esplicitamente lo scarico dei dati su disco, o dal demone di sistema
+\cmd{update} che esegue lo scarico dei dati ad intervalli di tempo fissi: il
+valore tradizionale, usato da BSD, per l'update dei dati è ogni 30 secondi, ma
+in Linux ilvalore utilizzato è di 5 secondi; con le nuove versioni poi, è il
+kernel che si occupa direttamente di tutto quanto.
+
+Quando si vogliono scaricare soltanto i dati di un file (ad esempio essere
+sicuri che i dati di un database sono stati registrati su disco) si possono
+usare le due funzioni \func{fsync} e \func{fdatasync}, i cui prototipi sono:
+\begin{functions}
+ \headdecl{unistd.h}
+ \funcdecl{int fsync(int fd)}
+ Sincronizza dati e metadati del file \param{fd}
+ \funcdecl{int fdatasync(int fd)}
+ Sincronizza i dati del file \param{fd}.
+
+ \bodydesc{La funzione ritorna 0 in caso di successo e -1 in caso di errore,
+ nel qual caso \var{errno} assume i valori:
+ \begin{errlist}
+ \item[\macro{EINVAL}] \param{fd} è un file speciale che non supporta la
+ sincronizzazione.
+ \end{errlist}
+ ed inoltre \macro{EBADF}, \macro{EROFS} e \macro{EIO}.}
+\end{functions}
+
+Entrambe le funzioni forzano la sincronizzazione col disco di tutti i dati del
+file specificato, ed attendono fino alla conclusione delle operazioni;
+\func{fsync} forza anche la sincronizzazione dei metadati del file (che
+riguardano sia le modifiche alle tabelle di allocazione dei settori, che gli
+altri dati contenuti nell'inode che si leggono con \var{fstat} come i tempi
+del file).
+
+Si tenga presente che questo non comporta la sincronizzazione della
+directory che contiene il file (e scrittura della relativa voce su
+disco) che deve essere effettuata esplicitamente.\footnote{in realtà per
+ il filesystem \acr{ext2}, quando lo si monta con l'opzione \cmd{sync},
+ il kernel provvede anche alla sincronizzazione automatica delle voci
+ delle directory.}
+
+
+\subsection{La funzioni \func{dup} e \func{dup2}}
+\label{sec:file_dup}
+
+Abbiamo già visto in \secref{sec:file_sharing} come un processo figlio
+condivida gli stessi file descriptor del padre; è possibile però ottenere un
+comportamento analogo all'interno di uno stesso processo \textit{duplicando}
+un file descriptor. Per far questo si usa la funzione \func{dup} il cui
+prototipo è:
+\begin{prototype}{unistd.h}{int dup(int oldfd)}
+ Crea una copia del file descriptor \param{oldfd}.
+
+ \bodydesc{La funzione ritorna il nuovo file descriptor in caso di successo e
+ -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei
+ valori:
+ \begin{errlist}
+ \item[\macro{EBADF}] \param{oldfd} non è un file aperto.
+ \item[\macro{EMFILE}] si è raggiunto il numero massimo consentito di file
+ descriptor aperti.
+ \end{errlist}}
+\end{prototype}
+
+La funzione ritorna, come \func{open}, il primo file descriptor libero. Il
+file descriptor è una copia esatta del precedente ed entrambi possono essere
+interscambiati nell'uso. Per capire meglio il funzionamento della funzione si
+può fare riferimento a \figref{fig:file_dup}: l'effetto della funzione è
+semplicemente quello di copiare il valore nella struttura \var{file\_struct},
+cosicché anche il nuovo file descriptor fa riferimento alla stessa voce
+nella \textit{file table}; per questo si dice che il nuovo file descriptor è
+\textsl{duplicato}, da cui il nome della funzione.
+
+\begin{figure}[htb]
+ \centering \includegraphics[width=13cm]{img/filedup}
+ \caption{Schema dell'accesso ai file duplicati}
+ \label{fig:file_dup}
+\end{figure}
+
+Si noti che per quanto illustrato in\figref{fig:file_dup} i file descriptor
+duplicati condivideranno eventuali lock, \textit{file status flag}, e
+posizione corrente. Se ad esempio si esegue una \func{lseek} per modificare la
+posizione su uno dei due file descriptor, essa risulterà modificata anche
+sull'altro (dato che quello che viene modificato è lo stesso campo nella voce
+della \textit{file table} a cui entrambi fanno riferimento). L'unica
+differenza fra due file descriptor duplicati è che ciascuno avrà il suo
+\textit{file descriptor flag}; a questo proposito va specificato che nel caso
+di \func{dup} il flag di \textit{close on exec} viene sempre cancellato nella
+copia.
+
+L'uso principale di questa funzione è per la redirezione dell'input e
+dell'output fra l'esecuzione di una \func{fork} e la successiva \func{exec};
+diventa così possibile associare un file (o una pipe) allo standard input o
+allo standard output (torneremo sull'argomento in \secref{sec:ipc_pipe_use},
+quando tratteremo le pipe). Per fare questo in genere occorre prima chiudere
+il file che si vuole sostituire, cossicché il suo file descriptor possa esser
+restituito alla chiamata di \func{dup}, come primo file descriptor
+disponibile.
-L'interfaccia standard unix per l'input/output sui file è su cinque funzioni
-\texttt{open}, \texttt{read}, \texttt{write}, \texttt{lseek}, \texttt{close}
+Dato che questa è l'operazione più comune, è prevista una diversa versione
+della funzione, \func{dup2}, che permette di specificare esplicitamente qual'è
+il valore di file descriptor che si vuole avere come duplicato; il suo
+prototipo è:
+\begin{prototype}{unistd.h}{int dup2(int oldfd, int newfd)}
+
+ Rende \param{newfd} una copia del file descriptor \param{oldfd}.
+
+ \bodydesc{La funzione ritorna il nuovo file descriptor in caso di successo e
+ -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\macro{EBADF}] \param{oldfd} non è un file aperto o \param{newfd} ha un
+ valore fuori dall'intervallo consentito per i file descriptor.
+ \item[\macro{EMFILE}] si è raggiunto il numero massimo consentito di file
+ descriptor aperti.
+ \end{errlist}}
+\end{prototype}
+\noindent e qualora il file descriptor \param{newfd} sia già aperto (come
+avviene ad esempio nel caso della duplicazione di uno dei file standard) esso
+sarà prima chiuso e poi duplicato.
+La duplicazione dei file descriptor può essere effettuata anche usando la
+funzione di controllo dei file \func{fnctl} (che esamineremo in
+\secref{sec:file_fcntl}) con il parametro \macro{F\_DUPFD}.
-\subsection{La funzione \texttt{open}}
-\label{sec:fileunix_open}
+L'operazione ha la sintassi \code{fnctl(oldfd, F\_DUPFD, newfd)} e se si usa 0
+come valore per \param{newfd} diventa equivalente a \func{dup}. La sola
+differenza, a parte i codici di errore, è che \func{dup2} chiude il nuovo file
+se è già aperto mentre \func{fcntl} apre il primo disponibile con un valore
+superiore, per cui per poterla usare come \func{dup2} occorrerebbe prima
+effettuare una \func{close}, perdendo l'atomicità dell'operazione.
-\subsection{La funzione \texttt{creat}}
-\label{sec:fileunix_creat}
-\subsection{La funzione \texttt{close}}
-\label{sec:fileunix_close}
+\subsection{La funzione \func{fcntl}}
+\label{sec:file_fcntl}
-\subsection{La funzione \texttt{lseek}}
-\label{sec:fileunix_lseek}
+Oltre alle operazioni base esaminate in \secref{sec:file_base_func} esistono
+tutta una serie di operazioni ausiliarie che è possibile eseguire su un file
+descriptor. Per queste operazioni di manipolazione delle varie proprietà di un
+file descriptor viene usata la funzione \func{fcntl} il cui prototipo è:
+\begin{functions}
+ \headdecl{unistd.h}
+ \headdecl{fcntl.h}
+ \funcdecl{int fcntl(int fd, int cmd)}
+ \funcdecl{int fcntl(int fd, int cmd, long arg)}
+ \funcdecl{int fcntl(int fd, int cmd, struct flock * lock)}
+ Esegue una delle possibili operazioni specificate da \param{cmd}
+ sul file \param{fd}.
+
+ \bodydesc{La funzione ha valori di ritorno diversi a seconda
+ dell'operazione. In caso di errore il valore di ritorno è sempre -1 ed il
+ codice dell'errore è restituito nella variabile \var{errno}; i codici
+ possibili dipendono dal tipo di operazione, l'unico valido in generale è:
+ \begin{errlist}
+ \item[\macro{EBADF}] \param{fd} non è un file aperto.
+ \end{errlist}}
+\end{functions}
-\subsection{La funzione \texttt{read}}
-\label{sec:fileunix_read}
+Il comportamento di questa funzione è determinato dal valore del comando
+\param{cmd} che le viene fornito; in \secref{sec:file_dup} abbiamo incontrato
+un esempio per la duplicazione dei file descriptor, una lista dei possibili
+valori è riportata di seguito:
+\begin{basedescript}{\desclabelwidth{2.0cm}}
+\item[\macro{F\_DUPFD}] trova il primo file descriptor disponibile di valore
+ maggiore o uguale ad \param{arg} e ne fa una copia di \var{fd}. In caso di
+ successo ritorna il nuovo file descriptor. Gli errori possibili sono
+ \macro{EINVAL} se \param{arg} è negativo o maggiore del massimo consentito o
+ \macro{EMFILE} se il processo ha già raggiunto il massimo numero di
+ descrittori consentito.
+\item[\macro{F\_SETFD}] imposta il valore del \textit{file descriptor flag}
+ al valore specificato con \param{arg}. Al momento l'unico bit usato è
+ quello di \textit{close on exec}, identificato dalla costante
+ \macro{FD\_CLOEXEC}.
+\item[\macro{F\_GETFD}] ritorna il valore del \textit{file descriptor flag} di
+ \var{fd}, se \macro{FD\_CLOEXEC} è impostato i file descriptor aperti
+ vengono chiusi attraverso una \func{exec} altrimenti (il comportamento
+ predefinito) restano aperti.
+\item[\macro{F\_GETFL}] ritorna il valore del \textit{file status flag},
+ permette cioè di rileggere quei bit impostati da \func{open} all'apertura del
+ file che vengono memorizzati (quelli riportati nella prima e terza sezione
+ di \tabref{tab:file_open_flags}).
+\item[\macro{F\_SETFL}] imposta il \textit{file status flag} al valore
+ specificato da \param{arg}, possono essere impostati solo i bit riportati
+ nella terza sezione di \tabref{tab:file_open_flags}.\footnote{la pagina di
+ manuale riporta come impostabili solo \macro{O\_APPEND},
+ \macro{O\_NONBLOCK} e \macro{O\_ASYNC}.}
+\item[\macro{F\_GETLK}] richiede un controllo sul file lock specificato da
+ \param{lock}, sovrascrivendo la struttura da esso puntata con il risultato
+ (questa funzionalità è trattata in dettaglio in
+ \secref{sec:file_posix_lock}).
+\item[\macro{F\_SETLK}] richiede o rilascia un file lock a seconda di quanto
+ specificato nella struttura puntata da \param{lock}. Se il lock è tenuto da
+ qualcun'altro ritorna immediatamente restituendo -1 e imposta \var{errno} a
+ \macro{EACCES} o \macro{EAGAIN} (questa funzionalità è trattata in dettaglio
+ in \secref{sec:file_posix_lock}).
+\item[\macro{F\_SETLKW}] identica a \macro{F\_SETLK} eccetto per il fatto che
+ la funzione non ritorna subito ma attende che il blocco sia rilasciato. Se
+ l'attesa viene interrotta da un segnale la funzione restituisce -1 e imposta
+ \var{errno} a \macro{EINTR} (questa funzionalità è trattata in dettaglio in
+ \secref{sec:file_posix_lock}).
+\item[\macro{F\_GETOWN}] restituisce il \acr{pid} del processo o il process
+ group che è preposto alla ricezione dei segnali \macro{SIGIO} e
+ \macro{SIGURG} per gli eventi associati al file descriptor \var{fd}. Il
+ process group è restituito come valore negativo.
+\item[\macro{F\_SETOWN}] imposta il processo o process group che riceverà i
+ segnali \macro{SIGIO} e \macro{SIGURG} per gli eventi associati al file
+ descriptor \var{fd}. I process group sono impostati usando valori negativi.
+\item[\macro{F\_GETSIG}] restituisce il valore del segnale mandato quando ci
+ sono dati disponibili in input su un file descriptor aperto o impostato in
+ I/O asincrono. Il valore 0 indica il valore predefinito (che è
+ \macro{SIGIO}), un valore diverso da zero indica il segnale richiesto, (che
+ può essere lo stesso \macro{SIGIO}).
+\item[\macro{F\_SETSIG}] imposta il segnale da inviare quando diventa
+ possibile effettuare I/O sul file descriptor in caso di I/O asincrono. Il
+ valore zero indica di usare il segnale predefinito, \macro{SIGIO}. Un altro
+ valore (compreso lo stesso \macro{SIGIO}) specifica il segnale voluto; l'uso
+ di un valore diverso da zero permette inoltre, se si è installato il
+ manipolatore del segnale come \var{sa\_sigaction} usando
+ \macro{SA\_SIGINFO}, (vedi \secref{sec:sig_sigaction}), di rendere
+ disponibili al manipolatore informazioni ulteriori informazioni riguardo il
+ file che ha generato il segnale attraverso i valori restituiti in
+ \type{siginfo\_t} (come vedremo in
+ \secref{sec:file_asyncronous_io}).\footnote{i due comandi \macro{F\_SETSIG}
+ e \macro{F\_GETSIG} sono una estensione specifica di Linux.}
+\end{basedescript}
-\subsection{La funzione \texttt{write}}
-\label{sec:fileunix_write}
+La maggior parte delle funzionalità di \func{fcntl} sono troppo avanzate per
+poter essere affrontate in dettaglio a questo punto; saranno riprese più
+avanti quando affronteremo le problematiche ad esse relative (in particolare
+riprenderemo le tematiche relative all'I/O asincrono in
+\secref{sec:file_asyncronous_io} e quelle relative al \textit{file locking} in
+\secref{sec:file_locking}).
-\section{La condivisione dei files}
-\label{sec:fileunix_sharing}
+Per determinare le modalità di accesso inoltre è necessario estrarre i bit di
+accesso (ottenuti con il comando \macro{F\_GETFL}); infatti la definizione
+corrente non assegna bit separati a \macro{O\_RDONLY}, \macro{O\_WRONLY} e
+\macro{O\_RDWR},\footnote{posti rispettivamente ai valori 0, 1 e 2.} per cui il
+valore si ottiene eseguendo un AND binario del valore di ritorno di
+\func{fcntl} con la maschera \macro{O\_ACCMODE} anch'essa definita in
+\file{fcntl.h}.
-\subsection{Operazioni atomiche}
-\label{sec:fileunix_atomic}
-\section{Funzioni avanzate}
-\label{sec:fileunix_adv_func}
+\subsection{La funzione \func{ioctl}}
+\label{sec:file_ioctl}
-\subsection{La funzioni \texttt{dup} e \texttt{dup2}}
-\label{sec:fileunix_dup}
+Benché il concetto di \textit{everything is a file} si sia dimostratato molto
+valido anche per l'interazione con i più vari dispositivi, con cui si può
+interagire con le stesse funzioni usate per i normali file di dati,
+esisteranno sempre caratteristiche peculiari, specifiche dell'hardware e della
+funzionalità che ciascuno di essi provvede, che non possono venire comprese in
+questa interfaccia astratta (un caso tipico è l'impostazione della velocità di
+una porta seriale, o le dimensioni di un framebuffer).
-\subsection{La funzione \texttt{fcntl}}
-\label{sec:fileunix_fcntl}
+Per questo motivo l'architettura del sistema ha previsto l'esistenza di una
+funzione speciale, \func{ioctl}, con cui poter compiere operazioni specifiche
+per ogni singolo dispositivo. Il prototipo di questa funzione è:
+\begin{prototype}{sys/ioctl.h}{int ioctl(int fd, int request, ...)}
+ Manipola il dispositivo sottostante, usando il parametro \param{request} per
+ specificare l'operazione richiesta e il terzo parametro (usualmente di tipo
+ \param{char * argp} o \param{int argp}) per il trasferimento
+ dell'informazione necessaria.
+
+ \bodydesc{La funzione nella maggior parte dei casi ritorna 0, alcune
+ operazioni usano però il valore di ritorno per restituire informazioni. In
+ caso di errore viene sempre restituito -1 ed \var{errno} assumerà uno dei
+ valori:
+ \begin{errlist}
+ \item[\macro{ENOTTY}] il file \param{fd} non è associato con un device, o la
+ richiesta non è applicabile all'oggetto a cui fa riferimento \param{fd}.
+ \item[\macro{EINVAL}] gli argomenti \param{request} o \param{argp} non sono
+ validi.
+ \end{errlist}
+ ed inoltre \macro{EBADF} e \macro{EFAULT}.}
+\end{prototype}
-\subsection{La funzione \texttt{ioctl}}
-\label{sec:fileunix_ioctl}
+La funzione serve in sostanza per fare tutte quelle operazioni che non si
+adattano al design dell'architettura dei file e che non è possibile effettuare
+con le funzioni esaminate finora. Esse vengono selezionate attraverso il
+valore di \param{request} e gli eventuali risultati possono essere restituiti
+sia attraverso il valore di ritorno che attraverso il terzo argomento
+\param{argp}. Sono esempi delle operazioni gestite con una \func{ioctl}:
+\begin{itemize*}
+\item il cambiamento dei font di un terminale.
+\item l'esecuzione di una traccia audio di un CDROM.
+\item i comandi di avanti veloce e riavvolgimento di un nastro.
+\item il comando di espulsione di un dispositivo rimovibile.
+\item l'impostazione della velocità trasmissione di una linea seriale.
+\item l'impostazione della frequenza e della durata dei suoni emessi dallo
+ speaker.
+\end{itemize*}
+In generale ogni dispositivo ha un suo insieme di possibili diverse operazioni
+effettuabili attraverso \func{ioctl}, che sono definite nell'header file
+\file{sys/ioctl.h}, e devono essere usate solo sui dispositivi cui fanno
+riferimento. Infatti anche se in genere i valori di \param{request} sono
+opportunamente differenziati a seconda del dispositivo\footnote{il kernel usa
+ un apposito \textit{magic number} per distinguere ciascun dispositivo nella
+ definizione delle macro da usare per \param{request}, in modo da essere
+ sicuri che essi siano sempre diversi, ed il loro uso causi al più un errore.
+ Si veda il capitolo quinto di \cite{LinDevDri} per una trattazione
+ dettagliata dell'argomento.} in alcuni casi, relativi a valori assegnati
+prima che questa differenziazione diventasse pratica corrente si potrebbe
+avere
+Per questo motivo non è possibile fare altro che darne una descrizione
+generica; torneremo ad esaminare in seguito quelle relative ad alcuni casi
+specifici (ad esempio la gestione dei terminali è effettuata attraverso
+\func{ioctl} in quasi tutte le implementazioni di Unix), qui riportiamo solo i
+valori che sono definiti per ogni file:
+\begin{basedescript}{\desclabelwidth{2.0cm}}
+\item[\macro{FIOCLEX}] Imposta il bit di \textit{close on exec}.
+\item[\macro{FIONCLEX}] Cancella il bit di \textit{close on exec}.
+\item[\macro{FIOASYNC}] Abilita l'I/O asincrono.
+\item[\macro{FIONBIO}] Abilita l'I/O in modalità non bloccante.
+\end{basedescript}
+relativi ad operazioni comunque eseguibili anche attraverso \func{fcntl}.
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: "gapil"
+%%% End: