+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 bytes 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 settata a zero all'apertura del file. È possibile settarla 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)}
+ La funzione setta la posizione attuale nel file.
+
+ La funzione ritorna valore della posizione corrente in caso di successo e -1
+ in caso di errore nel qual caso \var{errno} viene settata ad uno dei valori:
+ \begin{errlist}
+ \item \macro{ESPIPE} \var{fd} è una pipe, un socket o una fifo.
+ \item \macro{EINVAL} \var{whence} non è un valore valido.
+ \end{errlist}
+ ed inoltre \macro{EBADF}.
+\end{functions}
+
+La nuova posizione è settata usando il valore specificato da \var{offset},
+sommato al riferimento dato da \var{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{description}
+\item \macro{SEEK\_SET} si fa riferimento all'inizio del file: il valore di
+ \var{offset} è la nuova posizione.
+\item \macro{SEEK\_CUR} si fa riferimento alla posizione corrente del file:
+ \var{offset} che può essere negativo e positivo.
+\item \macro{SEEK\_END} si fa riferimento alla fine del file: il valore di
+ \var{offset} può essere negativo e positivo.
+\end{description}
+
+Come accennato in \secref{sec:file_file_size} con \func{lseek} è possibile
+settare la posizione corrente anche al di la della 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
+\func{offset} si può riottenere la posizione corrente nel file chiamando la
+funzione con \func{lseek(fd, 0, SEEK\_CUR}.
+
+Si tenga presente inoltre che usare \macro{SEEK\_END} non assicura affatto che
+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 settata in precedenza.
+Questa è una potenziale sorgente di \textit{race condition}, e quando si vuole
+essere sicuri di scrivere alla fine del file questo deve essere posto in
+modalità \macro{O\_APPEND}.
+
+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 le \acr{tty}\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 al proposito. Infine alcuni device, ad esempio \file{/dev/null}, non
+causano un errore ma restituiscono un valore indefinito.
+
+
+\subsection{La funzione \func{read}}
+\label{sec:file_read}
+
+Per leggere da un file precedentemente aperto, si può la funzione \func{read},
+il cui prototipo è:
+\begin{prototype}{unistd.h}{ssize\_t read(int fd, void * buf, size\_t count)}
+
+ La funzione cerca di leggere \var{count} bytes dal file \var{fd} al buffer
+ \var{buf}.
+
+ La funzione ritorna il numero di byte letti in caso di successo e -1 in
+ caso di errore, nel qual caso \var{errno} viene settata ad uno dei valori:
+ \begin{errlist}
+ \item \macro{EINTR} la funzione è stata interrotta da un segnale prima di
+ aver potuto leggere quasiasi 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 è spostata automaticamente in
+avanti del numero di bytes 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 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 però bisogna sempre tenere
+presente.
+
+La prima e più ovvia di queste ragioni è che si è chiesto di leggere più bytes
+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. Se ripetessimo la lettura \func{read} restituirebbe uno zero.
+La condizione raggiungimento della fine del file non è un errore, e viene
+segnalata appunto da un valore di ritorno di \func{read} nullo, ripetere 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 la situazione è
+invece normale quando si legge da un terminale, o su una pipe. In tal caso
+infatti, se non ci sono dati in ingresso, la \func{read} si blocca 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.
+
+Lo stesso comportamento avviene caso di lettura dalla rete (cioè su un socket,
+come vedremo in \secref{sec:sock_io_behav}), o per certi dispositivi come le
+unità a nastro che restituiscono un singolo blocco di dati alla volta.
+
+In realtà anche le due condizioni segnalate dagli errori \func{EINTR} e
+\func{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 prendere è quella di rieseguire la funzione. Torneremo
+sull'argomento in \secref{sec:signal_xxx}.
+
+La seconda si verifica quando il file è in modalità non bloccante e non ci
+sono dati in ingresso: la funzione allora ritorna immediatamente con un errore
+\macro{EAGAIN}\footnote{sotto BSD questo per questo errore viene usata la
+ costante \macro{EWOULDBLOCK}, in GNU/Linux questa è sinonima di
+ \macro{EAGAIN}.} indicando che occorrerà provare a ripetere la lettura.
+
+
+Lo standard Unix98\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
+ aggiutno con la versione 2.1} (vedi \secref{sec:intro_opengroup}) prevede la
+definizione di un'altra funzione di lettura, \func{pread}, che diventa
+accessibile con la definizione:
+\begin{verbatim}
+ #define _XOPEN_SOURCE 500
+\end{verbatim}
+il prototipo di questa funzione è:
+\begin{prototype}{unistd.h}
+{ssize\_t pread(int fd, void * buf, size\_t count, off\_t offset)}
+
+La funzione cerca di leggere \var{count} bytes dal file \var{fd}, a partire
+dalla posizione \var{offset}, nel buffer \var{buf}.
+
+La funzione ritorna il numero di byte letti in caso di successo e -1 in caso
+di errore, nel qual caso \var{errno} viene settata secondo i valori già visti
+per \func{read} e \func{lseek}.
+\end{prototype}
+
+Questa funzione serve quando si vogliono leggere dati dal file senza
+modificarne la posizione corrente. È equivalente alla esecuzione di una
+\func{read} e una \func{lseek}, ma dato che la posizione sul file può essere
+condivisa fra vari processi (vedi \secref{sec:file_sharing}), essa permette di
+eseguire l'operazione atomicamente. Il valore di \var{offset} fa riferimento
+all'inizio del file.
+
+
+\subsection{La funzione \func{write}}
+\label{sec:file_write}
+
+Per scrivere su un file si usa la funzione \func{write}, il cui prototipo è:
+\begin{prototype}{unistd.h}{ssize\_t write(int fd, void * buf, size\_t count)}
+
+ La funzione scrive \var{count} bytes dal buffer \var{buf} sul file \var{fd}.
+
+ La funzione ritorna il numero di byte scritti in caso di successo e -1 in
+ caso di errore, nel qual caso \var{errno} viene settata ad 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 scerivere quasiasi 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 bytes 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 bytes 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 una analoga 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)}
+
+La funzione cerca di scrivere sul file \var{fd}, a partire dalla posizione
+\var{offset}, \var{count} bytes dal buffer \var{buf}.
+
+La funzione ritorna il numero di byte letti in caso di successo e -1 in caso
+di errore, nel qual caso \var{errno} viene settata secondo i valori già visti
+per \func{write} e \func{lseek}.
+\end{prototype}
+
+
+
+\section{Caratteristiche avanzate}
+\label{sec:file_adv_func}
+
+In questa sezione approfondireme alcune delle caratteristiche più sottili
+della gestione file in un sistema unix-like, esaminando in dettaglio il
+comportamento delle funzioni base, inoltre tratteremo alcune funzioni che
+permettono di eseguire operazioni avanzate con i file.