Risistemati i prototipi delle funzioni, adesso dovrebbero essere un
[gapil.git] / fileunix.tex
index 5c1ab7cbed77a73703c256e3833f7bf79fa83bb4..10630c54c30d50d2cf21f94230a3506ab6b6585c 100644 (file)
@@ -1,12 +1,12 @@
-\chapter{L'interfaccia unix di I/O con i file}
+\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}, nativa di unix. Questa è
-l'interfaccia di basso livello, che non prevede funzioni evolute come la
-bufferizzazione o funzioni di lettura o scrittura formattata, ma è su questa
-che è costruita anche l'interfaccia standard dei file definita dallo standard
-ANSI C.
+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 in \capref{cha:files_std_interface}.
 
 
 
@@ -177,40 +177,35 @@ prototipo 
   \var{flags}, e, nel caso il file sia creato, con gli eventuali permessi
   specificati da \var{mode}.
   
-  La funzione ritorna il file descriptor in caso di successo e -1 in caso di
-  errore. In questo caso la variabile \var{errno} viene settata ad uno dei
-  valori:
+  \bodydesc{La funzione ritorna il file descriptor in caso di successo e -1 in
+    caso di errore. In questo caso la variabile \var{errno} viene settata ad
+    uno dei valori:
   \begin{errlist}
-  \item \macro{EEXIST} \var{pathname} esiste e si è specificato
+  \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
+  \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}
+  \item[\macro{ENOTDIR}] si è specificato \macro{O\_DIRECTORY} e \var{pathname}
     non è una directory.
-  \item \macro{ENXIO} si sono settati \macro{O\_NOBLOCK} o \macro{O\_WRONLY}
+  \item[\macro{ENXIO}] si sono settati \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
+  \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
+  \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
+  \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}.
+  \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. Questa caratteristica
-permette di prevedere qual'è il valore che si otterrà, e viene talvolta usata
-da alcune applicazioni per sostituire i file corrispondenti ai file standard
-di \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).
+sempre il file descriptor con il valore più basso. 
 
 \begin{table}[!htb]
   \centering
@@ -308,6 +303,13 @@ cio
   una 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 di
+\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
@@ -351,7 +353,9 @@ secondo le tre modalit
 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)
 del parametro \var{flags} da passare alla \func{open} per specificarne il
-comportamento.
+comportamento. I due flag \macro{O\_NOFOLLOW} e \macro{O\_DIRECTORY} sono
+estensioni specifiche di Linux, e deve essere usata definita la macro
+\macro{\_GNU\_SOURCE} per poterli usare.
 
 Nelle prime versioni di unix i flag specificabili per \func{open} erano solo
 quelli relativi alle modalità di accesso del file.  Per questo motivo per
@@ -374,13 +378,13 @@ descriptor ritorna disponibile; il suo prototipo 
 \begin{prototype}{unistd.h}{int close(int fd)}
   Chiude il descrittore \var{fd}. 
   
-  La funzione ritorna 0 in caso di successo e -1 n caso di errore. In questo
-  caso \var{errno} è settata ai valori:
+  \bodydesc{La funzione ritorna 0 in caso di successo e -1 n caso di errore.
+    In questo caso \var{errno} è settata ai valori:
   \begin{errlist}
-    \item \macro{EBADF}  \var{fd} non è un descrittore valido.
-    \item \macro{EINTR} la funzione è stata interrotta da un segnale.
+    \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}.
+  ed inoltre \macro{EIO}.}
 \end{prototype}
 
 La chiusura di un file rilascia ogni blocco (il \textit{file locking} è
@@ -390,7 +394,7 @@ 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 sui file descriptor
+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
@@ -404,9 +408,10 @@ 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} 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).
+\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).
 
 
 \subsection{La funzione \func{lseek}}
@@ -426,15 +431,16 @@ un valore qualsiasi con la funzione \func{lseek}, il cui prototipo 
   \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:
+  Setta 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} 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.
+    \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}.
+  ed inoltre \macro{EBADF}.}
 \end{functions}
 
 La nuova posizione è settata usando il valore specificato da \var{offset},
@@ -472,7 +478,7 @@ Non tutti i file supportano la capacit
 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
+  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.
@@ -481,56 +487,60 @@ 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 è:
+
+Una volta che un file è stato aperto 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)}
   
-  La funzione cerca di leggere \var{count} byte dal file \var{fd} al buffer
-  \var{buf}.
+  Cerca di leggere \var{count} byte 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:
+  \bodydesc{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
+  \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}.
+  \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}.
+  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 byte letti. Se \var{count} è zero la funzione
-restituisce zero senza nessun altro risultato.
+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 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.
+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. 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
+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
+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 la situazione è
-invece normale quando si legge da un terminale, o su una pipe. In tal caso
+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 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.
+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 certi dispositivi come le
-unità a nastro che restituiscono un singolo blocco di dati alla volta.
+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} è
@@ -542,15 +552,18 @@ La seconda si verifica quando il file 
 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.
+  \macro{EAGAIN}.} che nel caso indica soltanto che occorrerà provare a
+ripetere la lettura.
 
 
-Lo standard Unix98\footnote{questa funzione, e l'analoga \func{pwrite} sono
+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} (vedi \secref{sec:intro_opengroup}) prevede la
-definizione di un'altra funzione di lettura, \func{pread}, che diventa
-accessibile con la definizione:
+  aggiunto con la versione 2.1} (quello che viene chiamato normalmente Unix98,
+vedi \secref{sec:intro_opengroup}) è stata introdotta la definizione di
+un'altra funzione di lettura, \func{pread}, che diventa accessibile con la
+definizione:
 \begin{verbatim}
        #define _XOPEN_SOURCE 500
 \end{verbatim}
@@ -558,50 +571,52 @@ 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} byte dal file \var{fd}, a partire
-dalla posizione \var{offset}, nel buffer \var{buf}.
+Cerca di leggere \var{count} byte 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}.
+\bodydesc{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.
+\func{read} e una \func{lseek}, 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}
 
-Per scrivere su un file si usa la funzione \func{write}, il cui prototipo è:
+Una volta che un file è stato aperto 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)}
   
-  La funzione scrive \var{count} byte dal buffer \var{buf} sul file \var{fd}.
+  Scrive \var{count} byte 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:
+  \bodydesc{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
+  \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
+  \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 è
+  \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
+  \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
+  \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}.
+  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
@@ -618,20 +633,20 @@ i file ordinari il numero di byte scritti 
 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 è:
+Anche per \func{write} lo standard Unix98 definisce una 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)}
   
-La funzione cerca di scrivere sul file \var{fd}, a partire dalla posizione
-\var{offset}, \var{count} byte dal buffer \var{buf}.
+Cerca di scrivere sul file \var{fd}, a partire dalla posizione \var{offset},
+\var{count} byte 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}.
+\bodydesc{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}
-
+e per essa valgono le stesse considerazioni fatte per \func{pread}.
 
 
 \section{Caratteristiche avanzate}
@@ -767,6 +782,71 @@ assenza, diventa atomica essendo svolta tutta all'interno di una singola
 \func{open}.
 
 
+\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 da la garanzia assoluta che i dati siano integri dopo la chiamata,
+  l'hardware dei dischi è in genere dotato di un suo meccanismo interno 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 per l'update dei dati è ogni 30 secondi, ma in Linux era
+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 i codici restituiti in \var{errno} sono:
+  \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 metadata dell'inode (i dati
+di \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}
@@ -777,16 +857,16 @@ 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}.
   
-  La funzione crea una copia del file descriptor \param{oldfd}.
-  
-  La funzione ritorna il nuovo file descriptor in caso di successo e -1 in
-  caso di errore, nel qual caso \var{errno} viene settata ad uno dei valori:
+  \bodydesc{La funzione ritorna il nuovo file descriptor 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{EBADF} \param{oldfd} non è un file aperto.
-  \item \macro{EMFILE} si è raggiunto il numero massimo consentito di file
+  \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{errlist}}
 \end{prototype}
 
 La funzione ritorna, come \func{open}, il primo file descriptor libero. Il
@@ -817,16 +897,17 @@ Una diversa versione della funzione, \func{dup2} viene utilizzata per
 specificare esplicitamente il nuovo file descriptor; il suo prototipo è:
 \begin{prototype}{unistd.h}{int dup2(int oldfd, int newfd)}
   
-  La funzione rende \param{newfd} una copia del file descriptor \param{oldfd}.
+  Rende \param{newfd} una copia del file descriptor \param{oldfd}.
   
-  La funzione ritorna il nuovo file descriptor in caso di successo e -1 in
-  caso di errore, nel qual caso \var{errno} viene settata ad uno dei valori:
+  \bodydesc{La funzione ritorna il nuovo file descriptor 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{EBADF} \param{oldfd} non è un file aperto o \param{newfd} ha un
+  \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
+  \item[\macro{EMFILE}] si è raggiunto il numero massimo consentito di file
     descriptor aperti.
-  \end{errlist}
+  \end{errlist}}
 \end{prototype}
 \noindent la funzione chiude il file descriptor \param{newfd} se è aperto.
 
@@ -861,15 +942,16 @@ file descriptor viene usata la funzione \func{fcntl} il cui prototipo 
   \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)}
-  La funzione esegue una delle possibili operazioni specificate da \param{cmd}
+  Esegue una delle possibili operazioni specificate da \param{cmd}
   sul file \param{fd}.
   
-  La funzione ha valori di ritorno diversi a seconda dell'operazione. In caso
-  di errore il valore di ritorno è -1 e la variabile \var{errno} viene settata
-  ad un opportuno codice, quelli validi in generale sono:
+  \bodydesc{La funzione ha valori di ritorno diversi a seconda
+    dell'operazione. In caso di errore il valore di ritorno è -1 e la
+    variabile \var{errno} viene settata ad un opportuno codice, quelli validi
+    in generale sono:
   \begin{errlist}
-  \item \macro{EBADF} \param{oldfd} non è un file aperto.
-  \end{errlist}
+  \item[\macro{EBADF}] \param{oldfd} non è un file aperto.
+  \end{errlist}}
 \end{functions}
 
 Il comportamento di questa funzione è determinato dal valore del comando
@@ -936,7 +1018,15 @@ La maggior parte delle funzionalit
 poter essere affrontate in dettaglio a questo punto; saranno riprese più
 avanti quando affronteremo le problematiche ad esse relative.
 
-Per determinare le modalità di accesso inoltre può essere necessario usare la 
+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{La funzione \func{ioctl}}
 \label{sec:file_ioctl}
@@ -955,26 +1045,25 @@ per ogni singolo dispositivo.  Il prototipo di questa funzione 
 
 \begin{prototype}{sys/ioctl.h}{int ioctl(int fd, int request, ...)}
   
-  La funzione manipola il sottostante dispositivo, usando il parametro
-  \param{request} per specificare l'operazione richiesta e il terzo parametro
-  (che usualmente è di tipo \param{char * argp}) per passare o ricevere
-  l'informazione necessaria al dispositivo.
+  Manipola il dispositivo sottostante, usando il parametro \param{request} per
+  specificare l'operazione richiesta e il terzo parametro (usualmente di tipo
+  \param{char * argp}) per il trasferimento dell'informazione necessaria.
   
-  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 e \var{errno} viene settata ad uno dei valori
-  seguenti:
+  \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 e \var{errno} viene settata ad
+    uno dei valori seguenti:
   \begin{errlist}
-  \item \macro{ENOTTY} il file \param{fd} non è associato con un device.
-  \item \macro{EINVAL} gli argomenti \param{request} o \param{argp} non sono
+  \item[\macro{ENOTTY}] il file \param{fd} non è associato con un device.
+  \item[\macro{EINVAL}] gli argomenti \param{request} o \param{argp} non sono
     validi.
   \end{errlist}
-  ed inoltre \macro{EBADF} e \macro{EFAULT}.
+  ed inoltre \macro{EBADF} e \macro{EFAULT}.}
 \end{prototype}
 
 La funzione serve in sostanza per fare tutte quelle operazioni che non si
-adattano all'architettura di I/O di unix e che non è possibile effettuare con
-le funzioni esaminate finora. Per questo motivo non è possibile fare altro che
-una descrizione generica; torneremo ad esaminarla in seguito, quando si
-tratterà di applicarla ad alcune problematiche specifiche.
+adattano al design dell'architettura dei file e che non è possibile effettuare
+con le funzioni esaminate finora. Per questo motivo non è possibile fare altro
+che darne una descrizione generica; torneremo ad esaminarla in seguito, quando
+si tratterà di applicarla ad alcune problematiche specifiche.