Correzioni e aggiunte secondo le indicazioni di D. Masini, terza e
[gapil.git] / filestd.tex
index a106ff579ec7a447e9e54f1d40bd345e54bd2c92..8ab89567facfb0a44bc2b4a2315bfa0aa45b4080 100644 (file)
@@ -1,10 +1,10 @@
- \chapter{I file: l'interfaccia standard ANSI C}
+\chapter{I file: l'interfaccia standard ANSI C}
 \label{cha:files_std_interface}
 
 Esamineremo in questo capitolo l'interfaccia standard ANSI C per i file,
-quella che viene comunemente detta interfaccia degli \textit{stream}.
-Dopo una breve sezione introduttiva tratteremo le funzioni base per la
-gestione dell'input/output, mentre tratteremo le caratteristiche più avanzate
+quella che viene comunemente detta interfaccia degli \textit{stream}.  Dopo
+una breve sezione introduttiva tratteremo le funzioni base per la gestione
+dell'input/output, mentre tratteremo le caratteristiche più avanzate
 dell'interfaccia nell'ultima sezione.
 
 
@@ -26,17 +26,16 @@ costituire il nucleo\footnote{queste funzioni sono state implementate la prima
 \subsection{I \textit{file stream}}
 \label{sec:file_stream}
 
-Come più volte ribadito l'interfaccia dei file descriptor è una interfaccia di
+Come più volte ribadito, l'interfaccia dei file descriptor è un'interfaccia di
 basso livello, che non provvede nessuna forma di formattazione dei dati e
 nessuna forma di bufferizzazione per ottimizzare le operazioni di I/O.
 
-In \textit{Advanced Programming in the Unix Environment} Stevens descrive una
-serie di test sull'influenza delle dimensioni del blocco di dati (il parametro
-\param{buf} di \func{read} e \func{write}) nell'efficienza nelle operazioni di
-I/O con i file descriptor, evidenziando come le prestazioni ottimali si
-ottengano a partire da dimensioni del buffer dei dati pari a quelle dei
-blocchi del filesystem (il valore dato dal campo \var{st\_blksize} di
-\var{fstat}).
+In \cite{APUE} Stevens descrive una serie di test sull'influenza delle
+dimensioni del blocco di dati (il parametro \param{buf} di \func{read} e
+\func{write}) nell'efficienza nelle operazioni di I/O con i file descriptor,
+evidenziando come le prestazioni ottimali si ottengano a partire da dimensioni
+del buffer dei dati pari a quelle dei blocchi del filesystem (il valore dato
+dal campo \var{st\_blksize} di \var{fstat}).
 
 Se il programmatore non si cura di effettuare le operazioni in blocchi di
 dimensioni adeguate, le prestazioni sono inferiori.  La caratteristica
@@ -60,17 +59,17 @@ formattazioni), i file stream restano del tutto equivalenti ai file descriptor
 \secref{sec:file_access_control} per il controllo di accesso.
 
 
-\subsection{Gli oggetti \type{FILE}}
+\subsection{Gli oggetti \ctyp{FILE}}
 \label{sec:file_FILE}
 
 Per ragioni storiche la struttura di dati che rappresenta uno stream è stata
-chiamata \type{FILE}, questi oggetti sono creati dalle funzioni di libreria e
+chiamata \ctyp{FILE}, questi oggetti sono creati dalle funzioni di libreria e
 contengono tutte le informazioni necessarie a gestire le operazioni sugli
 stream, come la posizione corrente, lo stato del buffer e degli indicatori di
 stato e di fine del file.
 
 Per questo motivo gli utenti non devono mai utilizzare direttamente o
-allocare queste strutture, ma usare sempre puntatori del tipo \type{FILE
+allocare queste strutture, ma usare sempre puntatori del tipo \ctyp{FILE
   *} ottenuti dalla libreria stessa (tanto che in certi casi il termine
 di puntatore a file è diventato sinonimo di stream).  Tutte le funzioni
 della libreria che operano sui file accettano come parametri solo
@@ -88,27 +87,27 @@ rappresentano i canali standard di input/output prestabiliti; anche
 questi tre stream sono identificabili attraverso dei nomi simbolici
 definiti nell'header \file{stdio.h} che sono:
 
-\begin{itemize}
-\item \var{FILE *stdin} Lo \textit{standard input} cioè lo stream da
+\begin{basedescript}{\desclabelwidth{3.0cm}}
+\item[\var{FILE *stdin}] Lo \textit{standard input} cioè lo stream da
   cui il processo riceve ordinariamente i dati in ingresso. Normalmente
   è associato dalla shell all'input del terminale e prende i caratteri
   dalla tastiera.
-\item \var{FILE *stdout} Lo \textit{standard input} cioè lo stream su
+\item[\var{FILE *stdout}] Lo \textit{standard output} cioè lo stream su
   cui il processo invia ordinariamente i dati in uscita. Normalmente è
   associato dalla shell all'output del terminale e scrive sullo schermo.
-\item \var{FILE *stderr} Lo \textit{standard input} cioè lo stream su
+\item[\var{FILE *stderr}] Lo \textit{standard error} cioè lo stream su
   cui il processo è supposto inviare i messaggi di errore. Normalmente
   anch'esso è associato dalla shell all'output del terminale e scrive
   sullo schermo.
-\end{itemize}
+\end{basedescript}
 
 Nelle \acr{glibc} \var{stdin}, \var{stdout} e \var{stderr} sono
-effettivamente tre variabili di tipo \type{FILE *} che possono essere
+effettivamente tre variabili di tipo \ctyp{FILE *} che possono essere
 usate come tutte le altre, ad esempio si può effettuare una redirezione
 dell'output di un programma con il semplice codice:
 \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-    fclose (stdout);
-    stdout = fopen ("standard-output-file", "w");
+    fclose(stdout);
+    stdout = fopen("standard-output-file", "w");
 \end{lstlisting}
 ma in altri sistemi queste variabili possono essere definite da macro, e
 se si hanno problemi di portabilità e si vuole essere sicuri, diventa
@@ -118,25 +117,23 @@ opportuno usare la funzione \func{freopen}.
 \subsection{Le modalità di bufferizzazione}
 \label{sec:file_buffering}
 
-La bufferizzazione è una delle caratteristiche principali della
-interfaccia degli stream; lo scopo è quello di ridurre al minimo il
-numero di system call (\func{read} o \func{write}) eseguite nelle
-operazioni di input/output. Questa funzionalità è assicurata
-automaticamente dalla libreria, ma costituisce anche una degli aspetti
-più comunemente fraintesi, in particolare per quello che riguarda
-l'aspetto della scrittura dei dati sul file.
-
-I caratteri che vengono scritti su uno stream normalmente vengono
-accumulati in un buffer e poi trasmessi in blocco in maniera asincrona
-rispetto alla scrittura (quello che viene chiamato lo \textsl{scarico}
-dei dati, dall'inglese \textit{flush}) tutte le volte che il buffer
-viene riempito. Un comportamento analogo avviene anche in lettura (cioè
-dal file viene letto un blocco di dati, anche se se ne sono richiesti
-una quantità inferiore), ma la cosa ovviamente ha rilevanza inferiore,
-dato che i dati letti sono sempre gli stessi; in caso di scrittura
-invece, quando si ha un accesso contemporaneo allo stesso file (ad
-esempio da parte di un altro processo) si potranno vedere solo le parti
-effettivamente scritte, e non quelle ancora presenti nel buffer.
+La bufferizzazione è una delle caratteristiche principali dell'interfaccia
+degli stream; lo scopo è quello di ridurre al minimo il numero di system call
+(\func{read} o \func{write}) eseguite nelle operazioni di input/output. Questa
+funzionalità è assicurata automaticamente dalla libreria, ma costituisce anche
+uno degli aspetti più comunemente fraintesi, in particolare per quello che
+riguarda l'aspetto della scrittura dei dati sul file.
+
+I caratteri che vengono scritti su uno stream normalmente vengono accumulati
+in un buffer e poi trasmessi in blocco in maniera asincrona rispetto alla
+scrittura (quello che viene chiamato lo \textsl{scarico} dei dati,
+dall'inglese \textit{flush}) tutte le volte che il buffer viene riempito. Un
+comportamento analogo avviene anche in lettura (cioè dal file viene letto un
+blocco di dati, anche se ne sono richiesti una quantità inferiore), ma la cosa
+ovviamente ha rilevanza inferiore, dato che i dati letti sono sempre gli
+stessi; in caso di scrittura invece, quando si ha un accesso contemporaneo
+allo stesso file (ad esempio da parte di un altro processo) si potranno vedere
+solo le parti effettivamente scritte, e non quelle ancora presenti nel buffer.
 
 Allo stesso modo, se si sta facendo dell'input/output interattivo
 bisognerà tenere presente le caratteristiche delle operazioni di scarico
@@ -164,7 +161,7 @@ standard input siano aperti in modalit
 non fanno riferimento ad un dispositivo interattivo, e che lo standard
 error non sia mai aperto in modalità \textit{fully buffered}.
 
-Linux, come BSD e SVr4, specifica il comportamento di default in maniera
+Linux, come BSD e SVr4, specifica il comportamento predefinito in maniera
 ancora più precisa, e cioè impone che lo standard error sia sempre
 \textit{unbuffered} (in modo che i messaggi di errore siano mostrati il più
 rapidamente possibile) e che standard input e standard output siano aperti in
@@ -180,16 +177,16 @@ seconda del file o del dispositivo scelto.
 La modalità \textit{line buffered} è quella che necessita di maggiori
 chiarimenti e attenzioni per quel che concerne il suo funzionamento. Come già
 accennato nella descrizione, \emph{di norma} i dati vengono inviati al kernel
-alla ricezione di un carattere di a capo; questo non è vero in tutti i casi,
-infatti, dato che le dimensioni del buffer usato dalle librerie sono fisse, se
-le si eccedono si può avere uno scarico dei dati anche prima che sia stato
-inviato un carattere di \textit{newline}.
+alla ricezione di un carattere di \textsl{a capo} (\textit{newline}); questo
+non è vero in tutti i casi, infatti, dato che le dimensioni del buffer usato
+dalle librerie sono fisse, se le si eccedono si può avere uno scarico dei dati
+anche prima che sia stato inviato un carattere di \textit{newline}.
 
 Un secondo punto da tenere presente, particolarmente quando si ha a che fare
-con I/O interattivo, è che quando si effettua una lettura su uno stream che
-comporta l'accesso al kernel\footnote{questo vuol dire sempre se lo stream da
-  cui si legge è in modalità \textit{unbuffered}.} viene anche eseguito lo
-scarico di tutti i buffer degli stream in scrittura.
+con I/O interattivo, è che quando si effettua una lettura da uno stream che
+comporta l'accesso al kernel\footnote{questo vuol dire che lo stream da cui si
+  legge è in modalità \textit{unbuffered}.} viene anche eseguito lo scarico di
+tutti i buffer degli stream in scrittura.
 
 In \secref{sec:file_buffering_ctrl} vedremo come la libreria definisca delle
 opportune funzioni per controllare le modalità di bufferizzazione e lo scarico
@@ -209,10 +206,10 @@ corrente in uno stream.
 \subsection{Apertura e chiusura di uno stream}
 \label{sec:file_fopen}
 
-Le funzioni che si possono usare per aprire uno stream sono solo
-tre\footnote{\func{fopen} e \func{freopen} fanno parte dello standard
-  ANSI C, \func{fdopen} è parte dello standard POSIX.1.}, i loro
-prototipi sono:
+Le funzioni che si possono usare per aprire uno stream sono solo tre:
+\func{fopen}, \func{fdopen} e \func{freopen},\footnote{\func{fopen} e
+  \func{freopen} fanno parte dello standard ANSI C, \func{fdopen} è parte
+  dello standard POSIX.1.} i loro prototipi sono:
 \begin{functions}
   \headdecl{stdio.h}
   \funcdecl{FILE *fopen(const char *path, const char *mode)}
@@ -223,12 +220,11 @@ prototipi sono:
   Apre il file specificato da \param{path} associandolo allo stream
   specificato da \param{stream}, se questo è già aperto prima lo chiude.
   
-  \bodydesc{Le funzioni ritornano un puntatore valido in caso di
-    successo e \macro{NULL} in caso di errore, in tal caso \var{errno}
-    viene settata al valore ricevuto dalla funzione sottostante di cui è
-    fallita l'esecuzione.
+  \bodydesc{Le funzioni ritornano un puntatore valido in caso di successo e
+    \macro{NULL} in caso di errore, in tal caso \var{errno} assumerà il valore
+    ricevuto dalla funzione sottostante di cui è fallita l'esecuzione.
   
-    Gli errori pertanto possono essere quelli di \func{malloc} per tutte
+    Gli errori pertanto possono essere quelli di \code{malloc} per tutte
     e tre le funzioni, quelli \func{open} per \func{fopen}, quelli di
     \func{fcntl} per \func{fdopen} e quelli di \func{fopen},
     \func{fclose} e \func{fflush} per \func{freopen}.}
@@ -253,6 +249,7 @@ possono essere aperti con le funzioni delle librerie standard del C.
 
 \begin{table}[htb]
   \centering
+  \footnotesize
   \begin{tabular}[c]{|l|p{8cm}|}
     \hline
     \textbf{Valore} & \textbf{Significato}\\
@@ -275,16 +272,19 @@ possono essere aperti con le funzioni delle librerie standard del C.
     \texttt{a+} & Il file viene aperto (o creato se non esiste) in
     \textit{append mode}, l'accesso viene posto in lettura e scrittura. \\
     \hline
+    \texttt{b} & specifica che il file è binario, non ha alcun effetto. \\
+    \texttt{x} & l'apertura fallisce se il file esiste già. \\
+    \hline
   \end{tabular}
   \caption{Modalità di apertura di uno stream dello standard ANSI C che
-    sono sempre presenti in qualunque sistema POSIX}
+    sono sempre presenti in qualunque sistema POSIX.}
   \label{tab:file_fopen_mode}
 \end{table}
 
 In realtà lo standard ANSI C prevede un totale di 15 possibili valori
 diversi per \param{mode}, ma in \tabref{tab:file_fopen_mode} si sono
 riportati solo i sei valori effettivi, ad essi può essere aggiunto pure
-il carattere \func{b} (come ultimo carattere o nel mezzo agli altri per
+il carattere \texttt{b} (come ultimo carattere o nel mezzo agli altri per
 le stringhe di due caratteri) che in altri sistemi operativi serve a
 distinguere i file binari dai file di testo; in un sistema POSIX questa
 distinzione non esiste e il valore viene accettato solo per
@@ -304,23 +304,22 @@ valore \verb|STRING| 
 e \func{fopen} marca il file per l'uso dei caratteri estesi e abilita le
 opportune funzioni di conversione in lettura e scrittura.
 
-Inoltre nel caso si usi \func{fdopen} i valori specificati da
-\param{mode} devono essere compatibili con quelli con cui il file
-descriptor è stato aperto. Inoltre i modi \cmd{w} e \cmd{w+} non
-troncano il file. La posizione nello stream viene settata a quella
-corrente nel file descriptor, e le variabili di errore e di fine del
-file (vedi \secref{sec:file_io}) sono cancellate. Il file non viene
-duplicato e verrà chiuso alla chiusura dello stream.
+Nel caso si usi \func{fdopen} i valori specificati da \param{mode} devono
+essere compatibili con quelli con cui il file descriptor è stato aperto.
+Inoltre i modi \cmd{w} e \cmd{w+} non troncano il file. La posizione nello
+stream viene impostata a quella corrente nel file descriptor, e le variabili di
+errore e di fine del file (vedi \secref{sec:file_io}) sono cancellate. Il file
+non viene duplicato e verrà chiuso alla chiusura dello stream.
 
 I nuovi file saranno creati secondo quanto visto in
-\secref{sec:file_ownership} ed avranno i permessi di accesso settati al
+\secref{sec:file_ownership} ed avranno i permessi di accesso impostati al
 valore \macro{S\_IRUSR|S\_IWUSR|S\_IRGRP|S\_IWGRP|S\_IROTH|S\_IWOTH}
 (pari a \macro{0666}) modificato secondo il valore di \acr{umask} per il
 processo (si veda \secref{sec:file_umask}).
 
 In caso di file aperti in lettura e scrittura occorre ricordarsi che c'è
-di messo una bufferizzazione; per questo motivo lo standard ANSI C
-richiede che ci sia una operazione di posizionamento fra una operazione
+di mezzo una bufferizzazione; per questo motivo lo standard ANSI C
+richiede che ci sia un'operazione di posizionamento fra un'operazione
 di output ed una di input o viceversa (eccetto il caso in cui l'input ha
 incontrato la fine del file), altrimenti una lettura può ritornare anche
 il risultato di scritture precedenti l'ultima effettuata. 
@@ -330,7 +329,7 @@ una scrittura una delle funzioni \func{fflush}, \func{fseek}, \func{fsetpos} o
 \func{rewind} prima di eseguire una rilettura; viceversa nel caso in cui si
 voglia fare una scrittura subito dopo aver eseguito una lettura occorre prima
 usare una delle funzioni \func{fseek}, \func{fsetpos} o \func{rewind}. Anche
-una operazione nominalmente nulla come \func{fseek(file, 0, SEEK\_CUR)} è
+un'operazione nominalmente nulla come \code{fseek(file, 0, SEEK\_CUR)} è
 sufficiente a garantire la sincronizzazione.
 
 Una volta aperto lo stream, si può cambiare la modalità di bufferizzazione
@@ -342,7 +341,7 @@ Uno stream viene chiuso con la funzione \func{fclose} il cui prototipo 
   Chiude lo stream \param{stream}. 
   
   \bodydesc{Restituisce 0 in caso di successo e \macro{EOF} in caso di errore,
-    nel qual caso setta \var{errno} a \macro{EBADF} se il file descriptor
+    nel qual caso imposta \var{errno} a \macro{EBADF} se il file descriptor
     indicato da \param{stream} non è valido, o uno dei valori specificati
     dalla sottostante funzione che è fallita (\func{close}, \func{write} o
     \func{fflush}).}
@@ -355,9 +354,9 @@ dati presenti nei buffer in user space usati dalle \acr{glibc}; se si vuole
 essere sicuri che il kernel forzi la scrittura su disco occorrerà effettuare
 una \func{sync} (vedi \secref{sec:file_sync}).
 
-Linux supporta, come estensione implementata dalle \acr{glibc}, anche una
-altra funzione, \func{fcloseall}, che serve a chiudere tutti i file, il suo
-prototipo è:
+Linux supporta anche una altra funzione, \func{fcloseall}, come estensione GNU
+implementata dalle \acr{glibc}, accessibile avendo definito
+\macro{\_GNU\_SOURCE}, il suo prototipo è:
 \begin{prototype}{stdio.h}{int fcloseall(void)}
   Chiude tutti gli stream. 
   
@@ -384,9 +383,8 @@ modalit
 \item\textsl{a caratteri} in cui si legge/scrive un carattere alla
   volta (con la bufferizzazione gestita automaticamente dalla libreria),
   vedi \secref{sec:file_char_io}.
-\item\textsl{di linea} in cui si legge/scrive una linea (terminata dal
-  carattere di newline \verb|\n|) alla volta, vedi
-  \secref{sec:file_line_io}.
+\item\textsl{di linea} in cui si legge/scrive una linea alla volta (terminata
+  dal carattere di newline \verb|'\n'|), vedi \secref{sec:file_line_io}.
 \end{enumerate*}
 ed inoltre la modalità di input/output formattato.
 
@@ -394,25 +392,25 @@ A differenza dell'interfaccia dei file descriptor, con gli stream il
 raggiungimento della fine del file è considerato un errore, e viene
 notificato come tale dai valori di uscita delle varie funzioni. Nella
 maggior parte dei casi questo avviene con la restituzione del valore
-intero (di tipo \type{int}) \macro{EOF}\footnote{la costante deve essere
+intero (di tipo \ctyp{int}) \macro{EOF}\footnote{la costante deve essere
   negativa, le \acr{glibc} usano -1, altre implementazioni possono avere
-  valori diversi.}  definito anch'esso nell'header \func{stdlib.h}.
+  valori diversi.}  definito anch'esso nell'header \file{stdlib.h}.
 
 Dato che le funzioni dell'interfaccia degli stream sono funzioni di libreria
-che si appoggiano a delle system call, esse non settano direttamente la
-variabile \var{errno}, che mantiene il valore settato dalla system call che ha
-riportato l'errore. 
+che si appoggiano a delle system call, esse non impostano direttamente la
+variabile \var{errno}, che mantiene il valore impostato dalla system call che
+ha riportato l'errore.
 
 Siccome la condizione di end-of-file è anch'essa segnalata come errore, nasce
 il problema di come distinguerla da un errore effettivo; basarsi solo sul
 valore di ritorno della funzione e controllare il valore di \var{errno}
-infatti non basta, dato che quest'ultimo potrebbe essere stato settato in una
-altra occasione, (si veda \secref{sec:sys_errno} per i dettagli del
+infatti non basta, dato che quest'ultimo potrebbe essere stato impostato in
+una altra occasione, (si veda \secref{sec:sys_errno} per i dettagli del
 funzionamento di \var{errno}).
 
 Per questo motivo tutte le implementazioni delle librerie standard
 mantengono per ogni stream almeno due flag all'interno dell'oggetto
-\type{FILE}, il flag di \textit{end-of-file}, che segnala che si è
+\ctyp{FILE}, il flag di \textit{end-of-file}, che segnala che si è
 raggiunta la fine del file in lettura, e quello di errore, che segnala
 la presenza di un qualche errore nelle operazioni di input/output;
 questi due flag possono essere riletti dalle funzioni:
@@ -424,7 +422,7 @@ questi due flag possono essere riletti dalle funzioni:
   Controlla il flag di errore di \param{stream}.
   
   \bodydesc{Entrambe le funzioni ritornano un valore diverso da zero se
-    i relativi flag sono settati.}
+    i relativi flag sono impostati.}
 \end{functions}
 \noindent si tenga presente comunque che la lettura di questi flag segnala
 soltanto che c'è stato un errore, o che si è raggiunta la fine del file in una
@@ -436,9 +434,11 @@ la funzione \func{clearerr}, il cui prototipo 
 \begin{prototype}{stdio.h}{void clearerr(FILE *stream)}
   Cancella i flag di errore ed end-of-file di \param{stream}. 
 \end{prototype}
-\noindent in genere si usa questa funziona una volta che si sia identificata e
-corretta la causa di un errore per evitare di mantenere i flag attivi,
-così da poter rilevare una successiva ulteriore condizione di errore.
+\noindent in genere si usa questa funzione una volta che si sia identificata e
+corretta la causa di un errore per evitare di mantenere i flag attivi, così da
+poter rilevare una successiva ulteriore condizione di errore. Di questa
+funzione esiste una analoga \func{clearerr\_unlocked} che non esegue il blocco
+dello stream (vedi \secref{sec:file_stream_thread}).
 
 
 \subsection{Input/output binario}
@@ -470,6 +470,7 @@ In genere si usano queste funzioni quando si devono trasferire su file
 blocchi di dati binari in maniera compatta e veloce; un primo caso di uso
 tipico è quello in cui si salva un vettore (o un certo numero dei suoi
 elementi) con una chiamata del tipo:
+%\footnotesize
 \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
 int WriteVect(FILE *stream, double *vec, size_t nelem) 
 {
@@ -481,18 +482,20 @@ int WriteVect(FILE *stream, double *vec, size_t nelem)
     return nread;
 }
 \end{lstlisting}
+%\normalsize
 in questo caso devono essere specificate le dimensioni di ciascun
 elemento ed il numero di quelli che si vogliono scrivere. Un secondo
 caso è invece quello in cui si vuole trasferire su file una struttura;
 si avrà allora una chiamata tipo:
+%\footnotesize
 \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
 struct histogram {
     int nbins; 
     double max, min;
-    double * bin;
+    double *bin;
 } histo; 
 
-int WriteStruct(FILE * stream, struct histogram * histo, size_t nelem
+int WriteStruct(FILE *stream, struct histogram *histo
 {
     if ( fwrite(vec, sizeof(*histo), 1, stream) !=1) {
         perror("Write error");
@@ -500,18 +503,19 @@ int WriteStruct(FILE * stream, struct histogram * histo, size_t nelem)
     return nread;
 }
 \end{lstlisting}
+%\normalsize
 in cui si specifica la dimensione dell'intera struttura ed un solo
 elemento. 
 
 In realtà quello che conta nel trasferimento dei dati sono le dimensioni
-totali, che sono sempre pari al prodotto \func{size * nelem}; la sola
+totali, che sono sempre pari al prodotto \code{size * nelem}; la sola
 differenza è che le funzioni non ritornano il numero di byte scritti,
 ma il numero di elementi.
 
 La funzione \func{fread} legge sempre un numero intero di elementi, se
 incontra la fine del file l'oggetto letto parzialmente viene scartato
 (lo stesso avviene in caso di errore). In questo caso la posizione dello
-stream viene settata alla fine del file (e non a quella corrispondente
+stream viene impostata alla fine del file (e non a quella corrispondente
 alla quantità di dati letti).
 
 In caso di errore (o fine del file per \func{fread}) entrambe le
@@ -527,29 +531,27 @@ lo svantaggio di dipendere strettamente dalla piattaforma di sviluppo
 usata ed in genere possono essere riletti senza problemi solo dallo
 stesso programma che li ha prodotti.
 
-Infatti diversi compilatori possono eseguire ottimizzazioni diverse
-delle strutture dati e alcuni compilatori (come il \cmd{gcc}) possono
-anche scegliere se ottimizzare l'occupazione di spazio, impacchettando
-più strettamente i dati, o la velocità inserendo opportuni
-\textit{padding} per l'allineamento dei medesimi generando quindi output
-binari diversi. Inoltre altre incompatibilità si possono presentare
-quando entrano in gioco differenze di architettura hardware, come la
-dimensione del bus o la modalità di ordinamento dei bit o il formato
-delle variabili in floating point.
-
-Per questo motivo quando si usa l'input/output binario occorre sempre
-essere prendere le opportune precauzioni (in genere usare un formato di
-più alto livello che permetta di recuperare l'informazione completa),
-per assicurarsi che versioni diverse del programma siano in grado di
-rileggere i dati tenendo conto delle eventuali differenze.
+Infatti diversi compilatori possono eseguire ottimizzazioni diverse delle
+strutture dati e alcuni compilatori (come il \cmd{gcc}) possono anche
+scegliere se ottimizzare l'occupazione di spazio, impacchettando più
+strettamente i dati, o la velocità inserendo opportuni \textit{padding} per
+l'allineamento dei medesimi generando quindi output binari diversi. Inoltre
+altre incompatibilità si possono presentare quando entrano in gioco differenze
+di architettura hardware, come la dimensione del bus o la modalità di
+ordinamento dei bit o il formato delle variabili in floating point.
+
+Per questo motivo quando si usa l'input/output binario occorre sempre prendere
+le opportune precauzioni (in genere usare un formato di più alto livello che
+permetta di recuperare l'informazione completa), per assicurarsi che versioni
+diverse del programma siano in grado di rileggere i dati tenendo conto delle
+eventuali differenze.
 
 Le \acr{glibc} definiscono altre due funzioni per l'I/O binario, che
 evitano il lock implicito dello stream, usato per dalla librerie per la
 gestione delle applicazioni multi-thread (si veda
-\secref{sec:file_stream_thread} per i dettagli).
-
+\secref{sec:file_stream_thread} per i dettagli):
 \begin{functions}
-  \headdecl{stdio.h} 
+  \headdecl{stdio.h}
   
   \funcdecl{size\_t fread\_unlocked(void *ptr, size\_t size, size\_t
     nmemb, FILE *stream)}
@@ -576,11 +578,11 @@ rispettivi prototipi sono:
 
   \funcdecl{int getc(FILE *stream)} Legge un byte da \param{stream} e lo
   restituisce come intero. In genere è implementata come una macro. 
-
+  
   \funcdecl{int fgetc(FILE *stream)} Legge un byte da \param{stream} e lo
-  restituisce come intero. È una sempre una funzione.
+  restituisce come intero. È sempre una funzione.
   
-  \funcdecl{int getchar(void)} Equivalente a \func{getc(stdin)}.
+  \funcdecl{int getchar(void)} Equivalente a \code{getc(stdin)}.
   
   \bodydesc{Tutte queste funzioni leggono un byte alla volta, che viene
     restituito come intero; in caso di errore o fine del file il valore
@@ -589,28 +591,28 @@ rispettivi prototipi sono:
 
 A parte \func{getchar}, che si usa in genere per leggere un carattere da
 tastiera, le altre due funzioni sono sostanzialmente equivalenti. La
-differenza è che \func{gets} è ottimizzata al massimo e normalmente
+differenza è che \func{getc} è ottimizzata al massimo e normalmente
 viene implementata con una macro, per cui occorre stare attenti a cosa
 le si passa come argomento, infatti \param{stream} può essere valutato
 più volte nell'esecuzione, e non viene passato in copia con il
 meccanismo visto in \secref{sec:proc_var_passing}; per questo motivo se
-si passa unespressione si possono avere effetti indesiderati.
+si passa un'espressione si possono avere effetti indesiderati.
 
-Invece \func{fgets} è assicurata essere sempre una funzione, per questo
+Invece \func{fgetc} è assicurata essere sempre una funzione, per questo
 motivo la sua esecuzione normalmente è più lenta per via dell'overhead
 della chiamata, ma è altresì possibile ricavarne l'indirizzo, che può
 essere passato come parametro ad un altra funzione (e non si hanno i
 problemi accennati in precedenza con \param{stream}).
 
-Le tre funzioni restituiscono tutte un \type{unsigned char} convertito
-ad \type{int} (si usa \type{unsigned char} in modo da evitare
+Le tre funzioni restituiscono tutte un \ctyp{unsigned char} convertito
+ad \ctyp{int} (si usa \ctyp{unsigned char} in modo da evitare
 l'espansione del segno). In questo modo il valore di ritorno è sempre
 positivo, tranne in caso di errore o fine del file.
 
 Nelle estensioni GNU che provvedono la localizzazione sono definite tre
 funzioni equivalenti alle precedenti che invece di un carattere di un
 byte restituiscono un carattere in formato esteso (cioè di tipo
-\type{wint\_t}, il loro prototipo è:
+\ctyp{wint\_t}), il loro prototipo è:
 \begin{functions}
   \headdecl{stdio.h} 
   \headdecl{wchar.h} 
@@ -621,7 +623,7 @@ byte restituiscono un carattere in formato esteso (cio
   \funcdecl{wint\_t fgetwc(FILE *stream)} Legge un carattere esteso da
   \param{stream} È una sempre una funzione.
   
-  \funcdecl{wint\_t getwchar(void)} Equivalente a \func{getwc(stdin)}.
+  \funcdecl{wint\_t getwchar(void)} Equivalente a \code{getwc(stdin)}.
   
   \bodydesc{Tutte queste funzioni leggono un carattere alla volta, in
     caso di errore o fine del file il valore di ritorno è \macro{WEOF}.}
@@ -639,7 +641,7 @@ precedenti usate per leggere: \func{putc}, \func{fputc} e
   \funcdecl{int fputc(FILE *stream)} Scrive il carattere \param{c} su
   \param{stream}. È una sempre una funzione.
   
-  \funcdecl{int putchar(void)} Equivalente a \func{putc(stdin)}.
+  \funcdecl{int putchar(void)} Equivalente a \code{putc(stdin)}.
   
   \bodydesc{Le funzioni scrivono sempre un carattere alla volta, il cui
     valore viene restituito in caso di successo; in caso di errore o
@@ -647,19 +649,19 @@ precedenti usate per leggere: \func{putc}, \func{fputc} e
 \end{functions}
 
 Tutte queste funzioni scrivono sempre un byte alla volta, anche se
-prendono come parametro un \type{int} (che pertanto deve essere ottenuto
-con un cast da un \type{unsigned char}). Anche il valore di ritorno è
+prendono come parametro un \ctyp{int} (che pertanto deve essere ottenuto
+con un cast da un \ctyp{unsigned char}). Anche il valore di ritorno è
 sempre un intero; in caso di errore o fine del file il valore di ritorno
 è \macro{EOF}.
 
 Come nel caso dell'I/O binario le \acr{glibc} provvedono per ciascuna
 delle funzioni precedenti, come estensione GNU, una seconda funzione, il
-cui nome è ottenuto aggiungendo un \func{\_unlocked}, che esegue
+cui nome è ottenuto aggiungendo un \code{\_unlocked}, che esegue
 esattamente le stesse operazioni evitando però il lock implicito dello
 stream.
 
 Per compatibilità con SVID sono provviste anche due funzioni per leggere
-e scrivere una \textit{word} (che è sempre definita come \type{int}); i
+e scrivere una \textit{word} (che è sempre definita come \ctyp{int}); i
 loro prototipi sono:
 \begin{functions}
   \headdecl{stdio.h} 
@@ -675,19 +677,19 @@ loro prototipi sono:
 \func{fread} e \func{fwrite}, in quanto non è possibile distinguere il
 valore -1 da una condizione di errore che restituisce \macro{EOF}.
 
-Una degli usi più frequenti dell'input/output a caratteri è nei
-programmi di \textit{parsing} in cui si analizza il testo; in questo
-contesto diventa utile poter analizzare il carattere successivo da uno
-stream senza estrarlo effettivamente (la tecnica è detta \textit{peeking
-  ahead}) in modo che il programma possa regolarsi sulla base avendo
-dato una \textsl{sbirciatina} a quello che viene dopo. 
+Uno degli usi più frequenti dell'input/output a caratteri è nei programmi di
+\textit{parsing} in cui si analizza il testo; in questo contesto diventa utile
+poter analizzare il carattere successivo da uno stream senza estrarlo
+effettivamente (la tecnica è detta \textit{peeking ahead}) in modo che il
+programma possa regolarsi avendo dato una \textsl{sbirciatina} a quello che
+viene dopo.
 
 Nel nostro caso questo tipo di comportamento può essere realizzato prima
 leggendo il carattere, e poi rimandandolo indietro, cosicché ridiventi
 disponibile per una lettura successiva; la funzione che inverte la
 lettura si chiama \func{ungetc} ed il suo prototipo è:
 \begin{prototype}{stdio.h}{int ungetc(int c, FILE *stream)}
-  Rimanda indietro il carattere \param{c}, con un cast a \type{unsigned
+  Rimanda indietro il carattere \param{c}, con un cast a \ctyp{unsigned
     char}, sullo stream \param{stream}.
 
   \bodydesc{La funzione ritorna \param{c} in caso di successo e
@@ -723,10 +725,10 @@ scartati.
 \subsection{Input/output di linea}
 \label{sec:file_line_io}
 
-La terza ed ultima modalità di input/output non formattato è quella di
-linea, in cui legge o scrive una riga alla volta; questa è una modalità
-molto usata per l'I/O da terminale, ma che presenta le caratteristiche
-più controverse.
+La terza ed ultima modalità di input/output non formattato è quella di linea,
+in cui si legge o si scrive una riga alla volta; questa è una modalità molto
+usata per l'I/O da terminale, ma che presenta le caratteristiche più
+controverse.
 
 Le funzioni previste dallo standard ANSI C per leggere una linea sono
 sostanzialmente due, \func{gets} e \func{fgets}, i cui rispettivi
@@ -745,19 +747,19 @@ prototipi sono:
     di successo o \macro{NULL} in caso di errore.}
 \end{functions}
 
-Entrambe le funzioni effettuano la lettura (dal file specificato
-\func{fgets}, dallo standard input \func{gets}) di una linea di
-caratteri (terminata dal carattere \textit{newline}, \verb|\n|), ma
-\func{gets} sostituisce \verb|\n| con uno zero, mentre \func{fgets}
-aggiunge uno zero dopo il \textit{newline}, che resta dentro la
-stringa. Se la lettura incontra la fine del file (o c'è un errore) viene
-restituito un \macro{NULL}, ed il buffer \param{buf} non viene toccato.
-
+Entrambe le funzioni effettuano la lettura (dal file specificato \func{fgets},
+dallo standard input \func{gets}) di una linea di caratteri (terminata dal
+carattere \textit{newline}, \verb|'\n'|, quello mappato sul tasto di ritorno a
+capo della tastiera), ma \func{gets} sostituisce \verb|'\n'| con uno zero,
+mentre \func{fgets} aggiunge uno zero dopo il \textit{newline}, che resta
+dentro la stringa. Se la lettura incontra la fine del file (o c'è un errore)
+viene restituito un \macro{NULL}, ed il buffer \param{buf} non viene toccato.
 L'uso di \func{gets} è deprecato e deve essere assolutamente evitato; la
-funzione infatti non controlla il numero di byte letti, per cui nel caso
-la stringa letta superi le dimensioni del buffer, si avrà un
-\textit{buffer overflow}, con sovrascrittura della memoria del processo
-adiacente al buffer. 
+funzione infatti non controlla il numero di byte letti, per cui nel caso la
+stringa letta superi le dimensioni del buffer, si avrà un \textit{buffer
+  overflow}\index{buffer overflow}, con sovrascrittura della memoria del
+processo adiacente al buffer.\footnote{questa tecnica è spiegata in dettaglio
+  e con molta efficacia nell'ormai famoso articolo di Aleph1 \cite{StS}.}
 
 Questa è una delle vulnerabilità più sfruttate per guadagnare accessi
 non autorizzati al sistema (i cosiddetti \textit{exploit}), basta
@@ -766,17 +768,17 @@ forgiata per sovrascrivere gli indirizzi di ritorno nello stack
 (supposto che la \func{gets} sia stata chiamata da una subroutine), in
 modo da far ripartire l'esecuzione nel codice inviato nella stringa
 stessa (in genere uno \textit{shell code} cioè una sezione di programma
-lancia una shell).
-
-La funzione \func{fgets} non ha i precedenti problemi di \func{gets} in
-quanto prende in input la dimensione del buffer \param{size}, che non
-verrà mai ecceduta in lettura. La funzione legge fino ad un massimo di
-\param{size} caratteri (newline compreso), ed aggiunge uno zero di
-terminazione; questo comporta che la stringa possa essere al massimo di
-\var{size-1} caratteri.  Se la linea eccede la dimensione del buffer
-verranno letti solo \var{size-1} caratteri, ma la stringa sarà sempre
-terminata correttamente con uno zero finale; sarà possibile leggere i
-restanti caratteri in una chiamata successiva.
+che lancia una shell).
+
+La funzione \func{fgets} non ha i precedenti problemi di \func{gets} in quanto
+prende in input la dimensione del buffer \param{size}, che non verrà mai
+ecceduta in lettura. La funzione legge fino ad un massimo di \param{size}
+caratteri (newline compreso), ed aggiunge uno zero di terminazione; questo
+comporta che la stringa possa essere al massimo di \code{size-1} caratteri.  Se
+la linea eccede la dimensione del buffer verranno letti solo \code{size-1}
+caratteri, ma la stringa sarà sempre terminata correttamente con uno zero
+finale; sarà possibile leggere i rimanenti caratteri in una chiamata
+successiva.
 
 Per la scrittura di una linea lo standard ANSI C prevede altre due
 funzioni, \func{fputs} e \func{puts}, analoghe a quelle di lettura, i
@@ -794,13 +796,13 @@ rispettivi prototipi sono:
     successo o \macro{EOF} in caso di errore.}
 \end{functions}
 
-Dato che in questo caso si scrivono i dati in uscita \func{puts} non ha
-i problemi di \func{gets} ed è in genere la forma più immediata per
-scrivere messaggi sullo standard output; la funzione prende una stringa
-terminata da uno zero ed aggiunge automaticamente un newline. La
-differenza con \func{fputs} (a parte la possibilità di specificare un
-file diverso da \var{stdout}) è che quest'ultima non aggiunge il
-newline, che deve essere previsto esplicitamente. 
+Dato che in questo caso si scrivono i dati in uscita \func{puts} non ha i
+problemi di \func{gets} ed è in genere la forma più immediata per scrivere
+messaggi sullo standard output; la funzione prende una stringa terminata da
+uno zero ed aggiunge automaticamente il ritorno a capo. La differenza con
+\func{fputs} (a parte la possibilità di specificare un file diverso da
+\var{stdout}) è che quest'ultima non aggiunge il newline, che deve essere
+previsto esplicitamente.
 
 Come per le funzioni di input/output a caratteri esistono le estensioni
 per leggere e scrivere caratteri estesi, i loro prototipi sono:
@@ -817,15 +819,15 @@ per leggere e scrivere caratteri estesi, i loro prototipi sono:
     non negativo in caso di successo e \macro{NULL} o \macro{EOF} in
     caso di errore o fine del file.}
 \end{functions}
-\noindent il comportamento è identico a quello di \func{fgets} e
-\func{fputs} solo che tutto (numero di caratteri massimo, terminatore
-della stringa, newline) è espresso in termini di caratteri estesi
+\noindent il cui comportamento è identico a quello di \func{fgets} e
+\func{fputs} a parte il fatto che tutto (numero di caratteri massimo,
+terminatore della stringa, newline) è espresso in termini di caratteri estesi
 anziché di caratteri ASCII.
 
 Come nel caso dell'I/O binario e a caratteri nelle \acr{glibc} sono
 previste una serie di altre funzioni, estensione di tutte quelle
 illustrate finora (eccetto \func{gets} e \func{puts}), il cui nome si
-ottiene aggiungendo un \func{\_unlocked}, e che eseguono esattamente le
+ottiene aggiungendo un \code{\_unlocked}, e che eseguono esattamente le
 stesse operazioni delle loro equivalenti, evitando però il lock
 implicito dello stream (vedi \secref{sec:file_stream_thread}).
 
@@ -849,38 +851,37 @@ includere \file{stdio.h}. La prima delle due, \func{getline}, serve per
 leggere una linea terminata da un newline esattamente allo stesso modo
 di \func{fgets}, il suo prototipo è:
 \begin{prototype}{stdio.h}
-  {ssize\_t getline(char **buffer, size\_t *n, FILE *stream)} Legge una
-  linea dal file \param{stream} sul buffer indicato da \param{buffer}
-  riallocandolo se necessario (l'indirizzo del buffer e la sua
-  dimensione vengono sempre riscritte).
+  {ssize\_t getline(char **buffer, size\_t *n, FILE *stream)} Legge una linea
+  dal file \param{stream} copiandola sul buffer indicato da \param{buffer}
+  riallocandolo se necessario (l'indirizzo del buffer e la sua dimensione
+  vengono sempre riscritte).
 
   \bodydesc{La funzione ritorna il numero di caratteri letti in caso di
   successo e -1 in caso di errore o di raggiungimento della fine del
   file.}
 \end{prototype}
 
-La funzione permette di eseguire una lettura senza doversi preoccupare
-della eventuale lunghezza eccessiva della stringa da leggere. Essa
-prende come primo parametro l'indirizzo del puntatore al buffer su cui
-si vuole leggere la linea. Quest'ultimo \emph{deve} essere stato
-allocato in precedenza con una \func{malloc} (non si può passare
-l'indirizzo di un puntatore ad una variabile locale); come secondo
-parametro la funzione vuole l'indirizzo della variabile contenente le
-dimensioni del buffer suddetto.
+La funzione permette di eseguire una lettura senza doversi preoccupare della
+eventuale lunghezza eccessiva della stringa da leggere. Essa prende come primo
+parametro l'indirizzo del puntatore al buffer su cui si vuole copiare la
+linea. Quest'ultimo \emph{deve} essere stato allocato in precedenza con una
+\func{malloc} (non si può passare l'indirizzo di un puntatore ad una variabile
+locale); come secondo parametro la funzione vuole l'indirizzo della variabile
+contenente le dimensioni del buffer suddetto.
 
 Se il buffer di destinazione è sufficientemente ampio la stringa viene
 scritta subito, altrimenti il buffer viene allargato usando
 \func{realloc} e la nuova dimensione ed il nuovo puntatore vengono
 passata indietro (si noti infatti come per entrambi i parametri si siano
-usati dei \textit{value result argument}, passando dei puntatori anzichè
+usati dei \textit{value result argument}, passando dei puntatori anziché
 i valori delle variabili, secondo la tecnica spiegata in
 \secref{sec:proc_var_passing}).
 
-Se si passa alla funzione l'indirizzo ad un puntatore settato a
-\macro{NULL} e \var{*n} è zero, la funzione provvede da sola
-all'allocazione della memoria necessaria a contenere la linea. In tutti
-i casi si ottiene dalla funzione un puntatore all'inizio del testo della
-linea. Un esempio di codice può essere il seguente:
+Se si passa alla funzione l'indirizzo di un puntatore impostato a \macro{NULL}
+e \var{*n} è zero, la funzione provvede da sola all'allocazione della memoria
+necessaria a contenere la linea. In tutti i casi si ottiene dalla funzione un
+puntatore all'inizio del testo della linea letta. Un esempio di codice può
+essere il seguente:
 \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
     size_t n = 0; 
     char *ptr = NULL;
@@ -908,25 +909,24 @@ chiama \func{getdelim} ed il suo prototipo 
   carattere di newline come separatore di linea.
 \end{prototype}
 
-Il comportamento di \func{getdelim} è identico a quello di
-\func{getline} (che può essere implementata da questa passando
-\verb|'\n'| come valore di \param{delim}).
+Il comportamento di \func{getdelim} è identico a quello di \func{getline} (che
+può essere implementata da questa passando \verb|'\n'| come valore di
+\param{delim}).
 
 
-\subsection{Input/output formattato}
+\subsection{L'input/output formattato}
 \label{sec:file_formatted_io}
 
 L'ultima modalità di input/output è quella formattata, che è una delle
-caratteristiche più utilizzate delle librerie standard del C; in genere
-questa è la modalità in cui si esegue normalmente l'output su terminale
-poichè permette di stampare in maniera facile e veloce dati, tabelle e
-messaggi.
+caratteristiche più utilizzate delle librerie standard del C; in genere questa
+è la modalità in cui si esegue normalmente l'output su terminale poiché
+permette di stampare in maniera facile e veloce dati, tabelle e messaggi.
 
-L'output formattato viene eseguito con una delle 13 funzioni della
-famiglia \func{printf}; le tre più usate sono le seguenti:
+L'output formattato viene eseguito con una delle 13 funzioni della famiglia
+\func{printf}; le tre più usate sono le seguenti:
 \begin{functions}
   \headdecl{stdio.h} 
-  \funcdecl{int printf(const char *format, ...)} Stampa su \var{stdout}
+  \funcdecl{int printf(const char *format, ...)} Stampa su \file{stdout}
   gli argomenti, secondo il formato specificato da \param{format}.
   
   \funcdecl{int fprintf(FILE *stream, const char *format, ...)}  Stampa
@@ -940,60 +940,58 @@ famiglia \func{printf}; le tre pi
   \bodydesc{Le funzioni ritornano il numero di caratteri stampati.}
 \end{functions}
 \noindent le prime due servono per stampare su file (lo standard output
-o quello specificato) la terza permette di stampare su una stringa, in
-genere l'uso di \func{sprintf} è sconsigliato in quanto è possibile, se
-non si ha la sicurezza assoluta sulle dimensioni del risultato della
-stampa, eccedere le dimensioni di \param{str}; per questo motivo si
-consiglia l'uso dell'alternativa:
+o quello specificato) la terza permette di stampare su una stringa, in genere
+l'uso di \func{sprintf} è sconsigliato in quanto è possibile, se non si ha la
+sicurezza assoluta sulle dimensioni del risultato della stampa, eccedere le
+dimensioni di \param{str} con conseguente sovrascrittura di altre variabili e
+possibili buffer overflow; per questo motivo si consiglia l'uso
+dell'alternativa:
 \begin{prototype}{stdio.h}
-{snprintf(char *str, size\_t size, const char *format, ...);
+{snprintf(char *str, size\_t size, const char *format, ...)} 
   Identica a \func{sprintf}, ma non scrive su \param{str} più di
   \param{size} caratteri.
 \end{prototype}
 
 La parte più complessa di queste funzioni è il formato della stringa
 \param{format} che indica le conversioni da fare, da cui poi deriva il numero
-dei parametri che dovranno essere passati a seguire. La stringa è costituita
-da caratteri normali (tutti eccetto \texttt{\%}), che vengono passati
-invariati all'output, e da direttive di conversione, in cui devono essere
-sempre presenti il carattere \texttt{\%}, che introduce la direttiva, ed uno
-degli specificatori di conversione (riportati in \ntab) che la conclude. 
+dei parametri che dovranno essere passati a seguire. 
 
 \begin{table}[htb]
   \centering
+  \footnotesize
   \begin{tabular}[c]{|l|l|p{10cm}|}
     \hline
     \textbf{Valore} & \textbf{Tipo} & \textbf{Significato} \\
     \hline
     \hline
-   \cmd{\%d} &\type{int}         & Stampa un numero intero in formato decimale
+   \cmd{\%d} &\ctyp{int}         & Stampa un numero intero in formato decimale
                                    con segno \\
-   \cmd{\%i} &\type{int}         & Identico a \cmd{\%i} in output, \\
-   \cmd{\%o} &\type{unsigned int}& Stampa un numero intero come ottale\\
-   \cmd{\%u} &\type{unsigned int}& Stampa un numero intero in formato
+   \cmd{\%i} &\ctyp{int}         & Identico a \cmd{\%i} in output, \\
+   \cmd{\%o} &\ctyp{unsigned int}& Stampa un numero intero come ottale\\
+   \cmd{\%u} &\ctyp{unsigned int}& Stampa un numero intero in formato
                                    decimale senza segno \\
    \cmd{\%x}, 
-   \cmd{\%X} &\type{unsigned int}& Stampano un intero in formato esadecimale,
+   \cmd{\%X} &\ctyp{unsigned int}& Stampano un intero in formato esadecimale,
                                    rispettivamente con lettere minuscole e
                                    maiuscole. \\
-   \cmd{\%f} &\type{unsigned int}& Stampa un numero in virgola mobile con la
+   \cmd{\%f} &\ctyp{unsigned int}& Stampa un numero in virgola mobile con la
                                    notazione a virgola fissa \\
    \cmd{\%e}, 
-   \cmd{\%E} &\type{double} & Stampano un numero in virgola mobile con la
+   \cmd{\%E} &\ctyp{double} & Stampano un numero in virgola mobile con la
                               notazione esponenziale, rispettivamente con
                               lettere minuscole e maiuscole. \\
    \cmd{\%g}, 
-   \cmd{\%G} &\type{double} & Stampano un numero in virgola mobile con la
+   \cmd{\%G} &\ctyp{double} & Stampano un numero in virgola mobile con la
                               notazione più appropriate delle due precedenti,
                               rispettivamente con lettere minuscole e
                               maiuscole. \\
    \cmd{\%a}, 
-   \cmd{\%A} &\type{double} & Stampano un numero in virgola mobile in
+   \cmd{\%A} &\ctyp{double} & Stampano un numero in virgola mobile in
                               notazione esadecimale frazionaria\\
-   \cmd{\%c} &\type{int}    & Stampa un carattere singolo\\
-   \cmd{\%s} &\type{char *} & Stampa una stringa \\
-   \cmd{\%p} &\type{void *} & Stampa il valore di un puntatore\\
-   \cmd{\%n} &\type{\&int}  & Prende il numero di caratteri stampati finora\\
+   \cmd{\%c} &\ctyp{int}    & Stampa un carattere singolo\\
+   \cmd{\%s} &\ctyp{char *} & Stampa una stringa \\
+   \cmd{\%p} &\ctyp{void *} & Stampa il valore di un puntatore\\
+   \cmd{\%n} &\ctyp{\&int}  & Prende il numero di caratteri stampati finora\\
    \cmd{\%\%}&              & Stampa un \% \\
     \hline
   \end{tabular}
@@ -1002,87 +1000,250 @@ degli specificatori di conversione (riportati in \ntab) che la conclude.
   \label{tab:file_format_spec}
 \end{table}
 
-
-Il formato di una direttiva di conversione prevede una serie di possibili
-elementi opzionali oltre al \cmd{\%} e allo specificatore di conversione; in
-generale essa è sempre del tipo:
-\begin{center}
-\begin{verbatim}
-% [n. parametro $] [flag] [[larghezza] [. precisione]] [tipo] conversione
-\end{verbatim}
-\end{center}
-in cui i valori opzionali sono indicati fra parentesi, e prevedono la
-presenza, in questo ordine, di: uno specificatore per il parametro da usare
-(terminato da un \cmd{\$}, uno o più flag (riassunti in
-\tabref{tab:file_format_flag}) che controllano il formato di stampa della
-conversione (riassunti in \tabref{tab:file_format_type}), uno specificatore di
-larghezza, eventualmente seguito (per i numeri in virgola mobile) da un
-specificatore di precisione, uno specificatore del tipo di dato (che ne indica
-la lunghezza).
+La stringa è costituita da caratteri normali (tutti eccetto \texttt{\%}), che
+vengono passati invariati all'output, e da direttive di conversione, in cui
+devono essere sempre presenti il carattere \texttt{\%}, che introduce la
+direttiva, ed uno degli specificatori di conversione (riportati in
+\tabref{tab:file_format_spec}) che la conclude.
 
 \begin{table}[htb]
   \centering
+  \footnotesize
   \begin{tabular}[c]{|l|p{10cm}|}
     \hline
     \textbf{Valore} & \textbf{Significato}\\
     \hline
     \hline
-    \cmd{\#}  & \\
-    \cmd{0}   & \\
-    \cmd{-}   & \\
-    \cmd{' '} & \\
-    \cmd{+}   & \\
+    \cmd{\#} & Chiede la conversione in forma alternativa. \\
+    \cmd{0}  & La conversione è riempita con zeri alla sinistra del valore.\\
+    \cmd{-}  & La conversione viene allineata a sinistra sul bordo del campo.\\
+    \cmd{' '}& Mette uno spazio prima di un numero con segno di valore 
+               positivo\\
+    \cmd{+}  & Mette sempre il segno ($+$ o $-$) prima di un numero.\\
     \hline
   \end{tabular}
   \caption{I valori dei flag per il formato di \func{printf}}
   \label{tab:file_format_flag}
 \end{table}
 
-
+Il formato di una direttiva di conversione prevede una serie di possibili
+elementi opzionali oltre al \cmd{\%} e allo specificatore di conversione. In
+generale essa è sempre del tipo:
+\begin{center}
+\begin{verbatim}
+% [n. parametro $] [flag] [[larghezza] [. precisione]] [tipo] conversione
+\end{verbatim}
+\end{center}
+in cui tutti i valori tranne il \cmd{\%} e lo specificatore di conversione
+sono opzionali (e per questo sono indicati fra parentesi quadre); si possono
+usare più elementi opzionali, nel qual caso devono essere specificati in
+questo ordine:
+\begin{itemize*}
+\item uno specificatore del parametro da usare (terminato da un \cmd{\$}),
+\item uno o più flag (i cui valori possibili sono riassunti in
+  \tabref{tab:file_format_flag}) che controllano il formato di stampa della
+  conversione,
+\item uno specificatore di larghezza (un numero decimale), eventualmente
+  seguito (per i numeri in virgola mobile) da un specificatore di precisione
+  (un altro numero decimale),
+\item uno specificatore del tipo di dato, che ne indica la dimensione (i cui
+  valori possibili sono riassunti in \tabref{tab:file_format_type}).
+\end{itemize*}
+
+
+Dettagli ulteriori sulle varie opzioni possono essere trovati nella pagina di
+manuale di \func{printf} e nella documentazione delle \acr{glibc}.
 
 \begin{table}[htb]
   \centering
+  \footnotesize
   \begin{tabular}[c]{|l|p{10cm}|}
     \hline
     \textbf{Valore} & \textbf{Significato} \\
     \hline
     \hline
-    \cmd{hh} & \\
-    \cmd{h}  & \\
-    \cmd{l}  & \\
-    \cmd{ll} & \\
-    \cmd{L}  & \\
-    \cmd{q}  & \\
-    \cmd{j}  & \\
-    \cmd{z}  & \\
-    \cmd{t}  & \\
+    \cmd{hh} & una conversione intera corrisponde a un \ctyp{char} con o senza
+               segno, o il puntatore per il numero dei parametri \cmd{n} è di 
+               tipo \ctyp{char}.\\
+    \cmd{h}  & una conversione intera corrisponde a uno \ctyp{short} con o 
+               senza segno, o il puntatore per il numero dei parametri \cmd{n}
+               è di tipo \ctyp{short}.\\
+    \cmd{l}  & una conversione intera corrisponde a un \ctyp{long} con o 
+               senza segno, o il puntatore per il numero dei parametri \cmd{n}
+               è di tipo \ctyp{long}, o il carattere o la stringa seguenti
+               sono in formato esteso.\\ 
+    \cmd{ll} & una conversione intera corrisponde a un \ctyp{long long} con o 
+               senza segno, o il puntatore per il numero dei parametri \cmd{n}
+               è di tipo \ctyp{long long}.\\
+    \cmd{L}  & una conversione in virgola mobile corrisponde a un
+               \ctyp{double}.\\
+    \cmd{q}  & sinonimo di \cmd{ll}.\\
+    \cmd{j}  & una conversione intera corrisponde a un \type{intmax\_t} o 
+               \type{uintmax\_t}.\\
+    \cmd{z}  & una conversione intera corrisponde a un \type{size\_t} o 
+               \type{ssize\_t}.\\
+    \cmd{t}  & una conversione intera corrisponde a un \type{ptrdiff\_t}.\\
     \hline
   \end{tabular}
   \caption{Il modificatore di tipo di dato per il formato di \func{printf}}
   \label{tab:file_format_type}
 \end{table}
 
+Una versione alternativa delle funzioni di output formattato, che permettono
+di usare il puntatore ad una lista di argomenti (vedi
+\secref{sec:proc_variadic}), sono le seguenti:
+\begin{functions}
+  \headdecl{stdio.h} 
+  
+  \funcdecl{int vprintf(const char *format, va\_list ap)} Stampa su
+  \var{stdout} gli argomenti della lista \param{ap}, secondo il formato
+  specificato da \param{format}.
+  
+  \funcdecl{int vfprintf(FILE *stream, const char *format, va\_list ap)}
+  Stampa su \param{stream} gli argomenti della lista \param{ap}, secondo il
+  formato specificato da \param{format}.
+  
+  \funcdecl{int vsprintf(char *str, const char *format, va\_list ap)} Stampa
+  sulla stringa \param{str} gli argomenti della lista \param{ap}, secondo il
+  formato specificato da \param{format}.
+
+  \bodydesc{Le funzioni ritornano il numero di caratteri stampati.}
+\end{functions}
+\noindent con queste funzioni diventa possibile selezionare gli argomenti che
+si vogliono passare ad una routine di stampa, passando direttamente la lista
+tramite il parametro \param{ap}. Per poter far questo ovviamente la lista dei
+parametri dovrà essere opportunamente trattata (l'argomento è esaminato in
+\secref{sec:proc_variadic}), e dopo l'esecuzione della funzione l'argomento
+\param{ap} non sarà più utilizzabile (in generale dovrebbe essere eseguito un
+\macro{va\_end(ap)} ma in Linux questo non è necessario). 
+
+Come per \func{sprintf} anche per \func{vsprintf} esiste una analoga
+\func{vsnprintf} che pone un limite sul numero di caratteri che vengono
+scritti sulla stringa di destinazione:
+\begin{prototype}{stdio.h}
+{vsnprintf(char *str, size\_t size, const char *format, va\_list ap)} 
+  Identica a \func{vsprintf}, ma non scrive su \param{str} più di
+  \param{size} caratteri.
+\end{prototype}
+\noindent in modo da evitare possibili buffer overflow.
 
 
+Per eliminare alla radice questi problemi, le \acr{glibc} supportano una
+specifica estensione GNU che alloca dinamicamente tutto lo spazio necessario;
+l'estensione si attiva al solito definendo \macro{\_GNU\_SOURCE}, le due
+funzioni sono:
+\begin{functions}
+  \headdecl{stdio.h} 
+    
+  \funcdecl{int asprintf(char **strptr, const char *format, ...)}  Stampa gli
+  argomenti specificati secondo il formato specificato da \param{format} su
+  una stringa allocata automaticamente all'indirizzo \param{*strptr}.
+  
+  \funcdecl{int vasprintf(char **strptr, const char *format, va\_list ap)}
+  Stampa gli argomenti della lista \param{ap} secondo il formato specificato
+  da \param{format} su una stringa allocata automaticamente all'indirizzo
+  \param{*strptr}.
+
+  \bodydesc{Le funzioni ritornano il numero di caratteri stampati.}
+\end{functions}
+Entrambe le funzioni prendono come parametro \param{strptr} che deve essere
+l'indirizzo di un puntatore ad una stringa di caratteri, in cui verrà
+restituito (si ricordi quanto detto in \secref{sec:proc_var_passing} a
+proposito dei \textit{value result argument}) l'indirizzo della stringa
+allocata automaticamente dalle funzioni. Occorre inoltre ricordarsi di
+invocare \func{free} per liberare detto puntatore quando la stringa non serve
+più, onde evitare memory leak.
+
+Infine una ulteriore estensione GNU definisce le due funzioni \func{dprintf} e
+\func{vdprintf}, che prendono un file descriptor al posto dello stream. Altre
+estensioni permettono di scrivere con caratteri estesi. Anche queste funzioni,
+il cui nome è generato dalle precedenti funzioni aggiungendo una \texttt{w}
+davanti a \texttt{print}, sono trattate in dettaglio nella documentazione delle
+\acr{glibc}.
+
+In corrispondenza alla famiglia di funzioni \func{printf} che si usano per
+l'output formattato, l'input formattato viene eseguito con le funzioni della
+famiglia \func{scanf}; fra queste le tre più importanti sono:
+\begin{functions}
+  \headdecl{stdio.h} \funcdecl{int scanf(const char *format, ...)} Esegue una
+  scansione di \file{stdin} cercando una corrispondenza di quanto letto con il
+  formato dei dati specificato da \param{format}, ed effettua le relative
+  conversione memorizzando il risultato nei parametri seguenti.
+  
+  \funcdecl{int fscanf(FILE *stream, const char *format, ...)}  Analoga alla
+  precedente, ma effettua la scansione su \param{stream}.
+  
+  \funcdecl{int sscanf(char *str, const char *format, ...)} Analoga alle
+  precedenti, ma effettua la scansione dalla stringa \param{str}.
+  
+  \bodydesc{Le funzioni ritornano il numero di elementi assegnati. Questi
+    possono essere in numero inferiore a quelli specificati, ed anche zero.
+    Quest'ultimo valore significa che non si è trovata corrispondenza. In caso
+    di errore o fine del file viene invece restituito \macro{EOF}.}
+\end{functions}
+\noindent e come per le analoghe funzioni di scrittura esistono le relative
+\func{vscanf}, \func{vfscanf} \func{vsscanf} che usano un puntatore ad una
+lista di argomenti.
+
+Tutte le funzioni della famiglia delle \func{scanf} vogliono come argomenti i
+puntatori alle variabili che dovranno contenere le conversioni; questo è un
+primo elemento di disagio in quanto è molto facile dimenticarsi di questa
+caratteristica.
+
+Le funzioni leggono i caratteri dallo stream (o dalla stringa) di input ed
+eseguono un confronto con quanto indicato in \param{format}, la sintassi di
+questo parametro è simile a quella usata per l'analogo di \func{printf}, ma ci
+sono varie differenze.  Le funzioni di input infatti sono più orientate verso
+la lettura di testo libero che verso un input formattato in campi fissi. Uno
+spazio in \param{format} corrisponde con un numero qualunque di caratteri di
+separazione (che possono essere spazi, tabulatori, virgole etc.), mentre
+caratteri diversi richiedono una corrispondenza esatta. Le direttive di
+conversione sono analoghe a quelle di \func{printf} e si trovano descritte in
+dettaglio nelle pagine di manuale e nel manuale delle \acr{glibc}.
+
+Le funzioni eseguono la lettura dall'input, scartano i separatori (e gli
+eventuali caratteri diversi indicati dalla stringa di formato) effettuando le
+conversioni richieste; in caso la corrispondenza fallisca (o la funzione non
+sia in grado di effettuare una delle conversioni richieste) la scansione viene
+interrotta immediatamente e la funzione ritorna lasciando posizionato lo
+stream al primo carattere che non corrisponde.
+
+Data la notevole complessità di uso di queste funzioni, che richiedono molta
+cura nella definizione delle corrette stringhe di formato e sono facilmente
+soggette ad errori, e considerato anche il fatto che è estremamente macchinoso
+recuperare in caso di fallimento nelle corrispondenze, l'input formattato non
+è molto usato. In genere infatti quando si ha a che fare con un input
+relativamente semplice si preferisce usare l'input di linea ed effettuare
+scansione e conversione di quanto serve direttamente con una delle funzioni di
+conversione delle stringhe; se invece il formato è più complesso diventa più
+facile utilizzare uno strumento come \cmd{flex}\footnote{il programma
+  \cmd{flex}, è una implementazione libera di \cmd{lex} un generatore di
+  analizzatori lessicali, per i dettagli si può fare riferimento al manuale
+  \cite{flex}.} per generare un analizzatore lessicale o il
+\cmd{bison}\footnote{il programma \cmd{bison} è un clone del generatore di
+  parser \cmd{yacc}, maggiori dettagli possono essere trovati nel relativo
+  manuale \cite{bison}.} per generare un parser.
 
 
 \subsection{Posizionamento su uno stream}
 \label{sec:file_fseek}
 
-Come per i file descriptor è possibile anche con gli stream spostarsi
+Come per i file descriptor anche per gli stream è possibile spostarsi
 all'interno di un file per effettuare operazioni di lettura o scrittura in un
-punto prestabilito; questo fintanto che l'operazione di riposizionamento è
-supportata dal file sottostante lo stream, quando cioè si ha a che fare con
-quello che viene detto un file ad \textsl{accesso casuale}.
-
-In GNU/Linux ed in generale in ogni sistema unix-like la posizione nel
-file è espressa da un intero positivo, rappresentato dal tipo
-\type{off\_t}, il problema è alcune delle funzioni usate per il
-riposizionamento sugli stream originano dalle prime versioni di unix in
-cui questo tipo non era ancora stato definito, e che in altri sistemi
-non è detto che la posizione su un file venga sempre rappresentata con
-un numero di caratteri (ad esempio in VMS può essere rappresentata come
-numero di record, e offset rispetto al record corrente).
+punto prestabilito; sempre che l'operazione di riposizionamento sia supportata
+dal file sottostante lo stream, quando cioè si ha a che fare con quello che
+viene detto un file ad \textsl{accesso casuale}.\footnote{dato che in un
+  sistema Unix esistono vari tipi di file, come le fifo ed i dispositivi, non
+  è scontato che questo sia sempre vero.}
+
+In GNU/Linux ed in generale in ogni sistema unix-like la posizione nel file è
+espressa da un intero positivo, rappresentato dal tipo \type{off\_t}, il
+problema è che alcune delle funzioni usate per il riposizionamento sugli
+stream originano dalle prime versioni di Unix, in cui questo tipo non era
+ancora stato definito, e che in altri sistemi non è detto che la posizione su
+un file venga sempre rappresentata con il numero di caratteri dall'inizio (ad
+esempio in VMS può essere rappresentata come numero di record, più l'offset
+rispetto al record corrente).
 
 Tutto questo comporta la presenza di diverse funzioni che eseguono
 sostanzialmente le stesse operazioni, ma usano parametri di tipo
@@ -1099,64 +1260,109 @@ posizione in uno stream sono:
   all'inizio del file.
 \end{functions}
 
-L'uso di \func{fseek} è del tutto analogo a quello di \func{lseek} per i
-file descriptor, ed i parametri, a parte il tipo, hanno lo stesso
-significato; in particolare \param{whence} assume gli stessi valori già
-visti in \secref{sec:file_lseek}. La funzione restituisce 0 in caso di
-successo e -1 in caso di errore. 
+L'uso di \func{fseek} è del tutto analogo a quello di \func{lseek} per i file
+descriptor, ed i parametri, a parte il tipo, hanno lo stesso significato; in
+particolare \param{whence} assume gli stessi valori già visti in
+\secref{sec:file_lseek}.  La funzione restituisce 0 in caso di successo e -1
+in caso di errore.  La funzione \func{rewind} riporta semplicemente la
+posizione corrente all'inizio dello stream, ma non esattamente equivalente ad
+una \code{fseek(stream, 0L, SEEK\_SET)} in quanto vengono cancellati anche i
+flag di errore e fine del file.
 
-Per leggere la posizione corrente si usa invece la funzione \func{ftell}, il
+Per ottenere la posizione corrente si usa invece la funzione \func{ftell}, il
 cui prototipo è:
 \begin{prototype}{stdio.h}{long ftell(FILE *stream)} 
-  Legge la posizione attuale nello stream.
+  Legge la posizione attuale nello stream \param{stream}.
   
   \bodydesc{La funzione restituisce la posizione corrente, o -1 in caso
     di fallimento, che può esser dovuto sia al fatto che il file non
     supporta il riposizionamento che al fatto che la posizione non può
-    essere espressa con un \type{long int}}
+    essere espressa con un \ctyp{long int}}
 \end{prototype}
-
+\noindent la funzione restituisce la posizione come numero di byte
+dall'inizio dello stream. 
+
+Queste funzioni esprimono tutte la posizione nel file come un \ctyp{long int}.
+Dato che (ad esempio quando si usa un filesystem indicizzato a 64 bit) questo
+può non essere possibile lo standard POSIX ha introdotto le nuove funzioni
+\func{fgetpos} e \func{fsetpos}, che invece usano il nuovo tipo
+\type{fpos\_t}, ed i cui prototipi sono:
+\begin{functions}
+  \headdecl{stdio.h} 
   
+  \funcdecl{int fsetpos(FILE *stream, fpos\_t *pos)} Imposta la posizione
+  corrente nello stream \param{stream} al valore specificato da \param{pos}.
+  
+  \funcdecl{int fgetpos(FILE *stream, fpos\_t *pos)} Legge la posizione
+  corrente nello stream \param{stream} e la scrive in \param{pos}.
+  
+  \bodydesc{Le funzioni ritornano 0 in caso di successo e -1 in caso di
+    errore.}
+\end{functions}
+
+In Linux, a partire dalle glibc 2.1, sono presenti anche le due funzioni
+\func{fseeko} e \func{ftello}, che sono assolutamente identiche alle
+precedenti \func{fseek} e \func{ftell} ma hanno argomenti di tipo
+\type{off\_t} anziché di tipo \ctyp{long int}.
+
 
 
 \section{Funzioni avanzate}
 \label{sec:file_stream_adv_func}
 
-In questa sezione esamineremo le funzioni che permettono di controllare
-alcune caratteristiche più particolari degli stream, come la lettura
-degli attributi, le modalità di bufferizzazione, etc.
+In questa sezione esamineremo alcune funzioni avanzate che permettono di
+eseguire operazioni particolari sugli stream, come leggerne gli attributi,
+controllarne le modalità di bufferizzazione, gestire direttamente i lock
+impliciti per la programmazione multi thread.
 
 
 \subsection{Le funzioni di controllo}
 \label{sec:file_stream_cntrl}
 
-Al contrario di quanto avviene con i file descriptor le librerie standard del
-C non prevedono nessuna funzione come la \func{fcntl} per la lettura degli
-attributi degli stream; le \acr{glibc} però supportano alcune estensioni
-derivate da Solaris, che permettono di ottenere informazioni utili.
-
-In certi casi può essere necessario sapere se un certo stream è accessibile in
-lettura o scrittura. In genere questa informazione non è disponibile, e si
-deve ricordare come il file è stato aperto. La cosa può essere complessa se le
-operazioni vengono effettuate in una subroutine, che a questo punto
-necessiterà di informazioni aggiuntive rispetto al semplice puntatore allo
-stream; questo può essere evitato con le due funzioni \func{\_\_freadable} e
-\func{\_\_fwritable} i cui prototipi sono:
+Al contrario di quanto avviene con i file descriptor, le librerie standard del
+C non prevedono nessuna funzione come la \func{fcntl} per il controllo degli
+attributi dei file. Però, dato che ogni stream si appoggia ad un file
+descriptor, si può usare la funzione \func{fileno} per ottenere quest'ultimo,
+il prototipo della funzione è:
+\begin{prototype}{stdio.h}{int fileno(FILE *stream)}
+  Legge il file descriptor sottostante lo stream \param{stream}.
+  
+  \bodydesc{Restituisce il numero del file descriptor in caso di successo, e
+    -1 qualora \param{stream} non sia valido, nel qual caso imposta
+    \var{errno} a \macro{EBADF}.}
+\end{prototype}
+\noindent ed in questo modo diventa possibile usare direttamente \func{fcntl}.
+
+Questo permette di accedere agli attributi del file descriptor sottostante lo
+stream, ma non ci dà nessuna informazione riguardo alle proprietà dello stream
+medesimo.  Le \acr{glibc} però supportano alcune estensioni derivate da
+Solaris, che permettono di ottenere informazioni utili.
+
+Ad esempio in certi casi può essere necessario sapere se un certo stream è
+accessibile in lettura o scrittura. In genere questa informazione non è
+disponibile, e si deve ricordare come il file è stato aperto. La cosa può
+essere complessa se le operazioni vengono effettuate in una subroutine, che a
+questo punto necessiterà di informazioni aggiuntive rispetto al semplice
+puntatore allo stream; questo può essere evitato con le due funzioni
+\func{\_\_freadable} e \func{\_\_fwritable} i cui prototipi sono:
 \begin{functions}
   \headdecl{stdio\_ext.h}
-  \funcdecl{int \_\_freadable (FILE *stream)}
+  \funcdecl{int \_\_freadable(FILE *stream)}
   Restituisce un valore diverso da zero se \param{stream} consente la lettura.
 
   \funcdecl{int \_\_fwritable(FILE *stream)}  
   Restituisce un valore diverso da zero se \param{stream} consente la
   scrittura.
 \end{functions}
+\noindent che permettono di ottenere questa informazione.
 
-Altre due funzioni, \func{\_\_freading} e \func{\_\_fwriting} servono ad un
-uso ancora più specialistico, il loro prototipo è: 
+La conoscenza dell'ultima operazione effettuata su uno stream aperto è utile
+in quanto permette di trarre conclusioni sullo stato del buffer e del suo
+contenuto. Altre due funzioni, \func{\_\_freading} e \func{\_\_fwriting}
+servono a tale scopo, il loro prototipo è:
 \begin{functions}
   \headdecl{stdio\_ext.h}
-  \funcdecl{int \_\_freading (FILE *stream)}
+  \funcdecl{int \_\_freading(FILE *stream)}
   Restituisce un valore diverso da zero se \param{stream} è aperto in sola
   lettura o se l'ultima operazione è stata di lettura.
 
@@ -1165,24 +1371,167 @@ uso ancora pi
   scrittura o se l'ultima operazione è stata di scrittura.
 \end{functions}
 
-Le due funzioni hanno lo scopo di determinare di che tipo è stata l'ultima
+Le due funzioni permettono di determinare di che tipo è stata l'ultima
 operazione eseguita su uno stream aperto in lettura/scrittura; ovviamente se
 uno stream è aperto in sola lettura (o sola scrittura) la modalità dell'ultima
 operazione è sempre determinata; l'unica ambiguità è quando non sono state
-ancora eseguite operazioni, in questo caso le funzioni rispondono come se
-una operazione ci fosse comunque stata.
-
-La conoscenza dell'ultima operazione effettuata su uno stream aperto in
-lettura/scrittura è utile in quanto permette di trarre conclusioni sullo stato
-del buffer e del suo contenuto.
+ancora eseguite operazioni, in questo caso le funzioni rispondono come se una
+operazione ci fosse comunque stata.
 
 
 \subsection{Il controllo della bufferizzazione}
 \label{sec:file_buffering_ctrl}
 
 Come accennato in \secref{sec:file_buffering} le librerie definiscono una
-serie di funzioni che permettono di controllare il comportamento degli
-stream; se non si è 
+serie di funzioni che permettono di controllare il comportamento degli stream;
+se non si è specificato nulla, la modalità di buffering viene decisa
+autonomamente sulla base del tipo di file sottostante, ed i buffer vengono
+allocati automaticamente.
+
+Però una volta che si sia aperto lo stream (ma prima di aver compiuto
+operazioni su di esso) è possibile intervenire sulle modalità di buffering; la
+funzione che permette di controllare la bufferizzazione è \func{setvbuf}, il
+suo prototipo è:
+\begin{prototype}{stdio.h}{int setvbuf(FILE *stream, char *buf, int mode, 
+    size\_t size)}
+  
+  Imposta la bufferizzazione dello stream \param{stream} nella modalità
+  indicata da \param{mode}, usando \param{buf} come buffer di lunghezza
+  \param{size}.
+  
+  \bodydesc{Restituisce zero in caso di successo, ed un valore qualunque in
+    caso di errore, nel qual caso \var{errno} viene impostata opportunamente.}
+\end{prototype}
+
+La funzione permette di controllare tutti gli aspetti della bufferizzazione;
+l'utente può specificare un buffer da usare al posto di quello allocato dal
+sistema passandone alla funzione l'indirizzo in \param{buf} e la dimensione in
+\param{size}. 
+
+Ovviamente se si usa un buffer specificato dall'utente questo deve essere
+stato allocato e rimanere disponibile per tutto il tempo in cui si opera sullo
+stream. In genere conviene allocarlo con \func{malloc} e disallocarlo dopo la
+chiusura del file; ma fintanto che il file è usato all'interno di una
+funzione, può anche essere usata una variabile automatica. In \file{stdio.h} è
+definita la macro \macro{BUFSIZ}, che indica le dimensioni generiche del
+buffer di uno stream; queste vengono usate dalla funzione \func{setbuf}.  Non
+è detto però che tale dimensione corrisponda sempre al valore ottimale (che
+può variare a seconda del dispositivo).
+
+Dato che la procedura di allocazione manuale è macchinosa, comporta dei rischi
+(come delle scritture accidentali sul buffer) e non assicura la scelta delle
+dimensioni ottimali, è sempre meglio lasciare allocare il buffer alle funzioni
+di libreria, che sono in grado di farlo in maniera ottimale e trasparente
+all'utente (in quanto la disallocazione avviene automaticamente). Inoltre
+siccome alcune implementazioni usano parte del buffer per mantenere delle
+informazioni di controllo, non è detto che le dimensioni dello stesso
+coincidano con quelle su cui viene effettuato l'I/O.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+    \begin{tabular}[c]{|l|l|}
+      \hline
+      \textbf{Valore} & \textbf{Modalità} \\
+      \hline
+      \hline
+      \macro{\_IONBF} & \textit{unbuffered}\\
+      \macro{\_IOLBF} & \textit{line buffered}\\
+      \macro{\_IOFBF} & \textit{fully buffered}\\
+      \hline
+    \end{tabular}
+  \caption{Valori del parametro \param{mode} di \func{setvbuf} 
+    per l'impostazione delle modalità di bufferizzazione.}
+  \label{tab:file_stream_buf_mode}
+\end{table}
+
+Per evitare che \func{setvbuf} imposti il buffer basta passare un valore
+\macro{NULL} per \param{buf} e la funzione ignorerà il parametro \param{size}
+usando il buffer allocato automaticamente dal sistema.  Si potrà comunque
+modificare la modalità di bufferizzazione, passando in \param{mode} uno degli
+opportuni valori elencati in \tabref{tab:file_stream_buf_mode}. Qualora si
+specifichi la modalità non bufferizzata i valori di \param{buf} e \param{size}
+vengono sempre ignorati.
+
+Oltre a \func{setvbuf} le \acr{glibc} definiscono altre tre funzioni per la
+gestione della bufferizzazione di uno stream: \func{setbuf}, \func{setbuffer}
+e \func{setlinebuf}; i loro prototipi sono:
+\begin{functions}
+  \headdecl{stdio.h} 
+  
+  \funcdecl{void setbuf(FILE *stream, char *buf)} Disabilita la
+  bufferizzazione se \param{buf} è \macro{NULL}, altrimenti usa \param{buf}
+  come buffer di dimensione \macro{BUFSIZ} in modalità \textit{fully buffered}.
+  
+  \funcdecl{void setbuffer(FILE *stream, char *buf, size\_t size)} Disabilita
+  la bufferizzazione se \param{buf} è \macro{NULL}, altrimenti usa \param{buf}
+  come buffer di dimensione \param{size} in modalità \textit{fully buffered}.
+  
+  \funcdecl{void setlinebuf(FILE *stream)} Pone lo stream in modalità
+  \textit{line buffered}.
+\end{functions}
+\noindent tutte queste funzioni sono realizzate con opportune chiamate a
+\func{setvbuf} e sono definite solo per compatibilità con le vecchie librerie
+BSD. Infine le \acr{glibc} provvedono le funzioni non standard\footnote{anche
+  queste funzioni sono originarie di Solaris.} \func{\_\_flbf} e
+\func{\_\_fbufsize} che permettono di leggere le proprietà di bufferizzazione
+di uno stream; i cui prototipi sono:
+\begin{functions}
+  \headdecl{stdio\_ext.h} 
+  
+  \funcdecl{int \_\_flbf(FILE *stream)} Restituisce un valore diverso da zero
+  se \param{stream} è in modalità \textit{line buffered}.
+  
+  \funcdecl{size\_t \_\_fbufsize(FILE *stream)} Restituisce le dimensioni del
+  buffer di \param{stream}.
+\end{functions}
+
+Come già accennato, indipendentemente dalla modalità di bufferizzazione
+scelta, si può forzare lo scarico dei dati sul file con la funzione
+\func{fflush}, il suo prototipo è:
+\begin{prototype}{stdio.h}{int fflush(FILE *stream)}
+  
+  Forza la scrittura di tutti i dati bufferizzati dello stream \param{stream}.
+  
+  \bodydesc{Restituisce zero in caso di successo, ed \macro{EOF} in caso di
+    errore, impostando \var{errno} a \macro{EBADF} se \param{stream} non è
+    aperto o non è aperto in scrittura, o ad uno degli errori di
+    \func{write}.}
+\end{prototype}
+\noindent anche di questa funzione esiste una analoga
+\func{fflush\_unlocked}\footnote{accessibile definendo \macro{\_BSD\_SOURCE} o
+  \macro{\_SVID\_SOURCE} o \macro{\_GNU\_SOURCE}.} che non effettua il blocco
+dello stream.
+
+Se \param{stream} è \macro{NULL} lo scarico dei dati è forzato per tutti gli
+stream aperti. Esistono però circostanze, ad esempio quando si vuole essere
+sicuri che sia stato eseguito tutto l'output su terminale, in cui serve poter
+effettuare lo scarico dei dati solo per gli stream in modalità line buffered;
+per questo motivo le \acr{glibc} supportano una estensione di Solaris, la
+funzione \func{\_flushlbf}, il cui prototipo è:
+\begin{prototype}{stdio-ext.h}{void \_flushlbf(void)}
+  Forza la scrittura di tutti i dati bufferizzati degli stream in modalità
+  line buffered.
+\end{prototype}
+
+Si ricordi comunque che lo scarico dei dati dai buffer effettuato da queste
+funzioni non comporta la scrittura di questi su disco; se si vuole che il
+kernel dia effettivamente avvio alle operazioni di scrittura su disco occorre
+usare \func{sync} o \func{fsync} (si veda~\secref{sec:file_sync}).
+
+Infine esistono anche circostanze in cui si vuole scartare tutto l'output
+pendente; per questo si può usare \func{fpurge}, il cui prototipo è:
+\begin{prototype}{stdio.h}{int fpurge(FILE *stream)}
+  Cancella i buffer di input e di output dello stream \param{stream}.
+  
+  \bodydesc{Restituisce zero in caso di successo, ed \macro{EOF} in caso di
+    errore.}
+\end{prototype}
+
+La funzione scarta tutti i dati non ancora scritti (se il file è aperto in
+scrittura), e tutto l'input non ancora letto (se è aperto in lettura),
+compresi gli eventuali caratteri rimandati indietro con \func{ungetc}.
 
 
 \subsection{Gli stream e i thread}
@@ -1192,35 +1541,80 @@ Gli stream possono essere usati in applicazioni multi-thread allo stesso
 modo in cui sono usati nelle applicazioni normali, ma si deve essere
 consapevoli delle possibili complicazioni anche quando non si usano i
 thread, dato che l'implementazione delle librerie è influenzata
-pesantemente dalle richieste necessarie per garantirne l'uso coi thread.
-
-
-
+pesantemente dalle richieste necessarie per garantirne l'uso con i thread.
+
+Lo standard POSIX richiede che le operazioni sui file siano atomiche rispetto
+ai thread, per questo le operazioni sui buffer effettuate dalle funzioni di
+libreria durante la lettura e la scrittura di uno stream devono essere
+opportunamente protette (in quanto il sistema assicura l'atomicità solo per le
+system call). Questo viene fatto associando ad ogni stream un opportuno blocco
+che deve essere implicitamente acquisito prima dell'esecuzione di qualunque
+operazione.
+
+Ci sono comunque situazioni in cui questo non basta, come quando un thread
+necessita di compiere più di una operazione sullo stream atomicamente, per
+questo motivo le librerie provvedono anche delle funzioni che permettono la
+gestione esplicita dei blocchi sugli stream; queste funzioni sono disponibili
+definendo \macro{\_POSIX\_THREAD\_SAFE\_FUNCTIONS} ed i loro prototipi sono:
 \begin{functions}
   \headdecl{stdio.h}
   
-  \funcdecl{void flockfile(FILE *stream)} Esegue l'acquisizione del
-  lock dello stream \param{stream}, bloccandosi in caso il lock non
-  disponibile. 
+  \funcdecl{void flockfile(FILE *stream)} Esegue l'acquisizione del lock dello
+  stream \param{stream}, bloccandosi se il lock non è disponibile.
   
-  \funcdecl{int ftrylockfile(FILE *stream)} Tenta l'acquisizione del
-  lock dello stream \param{stream}, senza bloccarsi in caso il lock non sia
-  disponibile. Ritorna zero in caso di acquisizione del lock, diverso da
-  zero altrimenti.
+  \funcdecl{int ftrylockfile(FILE *stream)} Tenta l'acquisizione del lock
+  dello stream \param{stream}, senza bloccarsi se il lock non è disponibile.
+  Ritorna zero in caso di acquisizione del lock, diverso da zero altrimenti.
   
   \funcdecl{void funlockfile(FILE *stream)} Rilascia il lock dello
   stream \param{stream}.
 \end{functions}
+\noindent con queste funzioni diventa possibile acquisire un blocco ed
+eseguire tutte le operazioni volute, per poi rilasciarlo. 
+
+Ma, vista la complessità delle strutture di dati coinvolte, le operazioni di
+blocco non sono del tutto indolori, e quando il locking dello stream non è
+necessario (come in tutti i programmi che non usano i thread), tutta la
+procedura può comportare dei costi pesanti in termini di prestazioni. Per
+questo motivo abbiamo visto come alle usuali funzioni di I/O non formattato
+siano associate delle versioni \code{\_unlocked} (alcune previste dallo stesso
+standard POSIX, altre aggiunte come estensioni dalle \acr{glibc}) che possono
+essere usate quando il locking non serve\footnote{in certi casi dette funzioni
+  possono essere usate, visto che sono molto più efficienti, anche in caso di
+  necessità di locking, una volta che questo sia stato acquisito manualmente.}
+con prestazioni molto più elevate, dato che spesso queste versioni (come
+accade per \func{getc} e \func{putc}) sono realizzate come macro.
+
+La sostituzione di tutte le funzioni di I/O con le relative versioni
+\code{\_unlocked} in un programma che non usa i thread è però un lavoro
+abbastanza noioso; per questo motivo le \acr{glibc} provvedono al
+programmatore pigro un'altra via\footnote{anche questa mutuata da estensioni
+  introdotte in Solaris.} da poter utilizzare per disabilitare in blocco il
+locking degli stream: l'uso della funzione \func{\_\_fsetlocking}, il cui
+prototipo è:
+\begin{prototype}{stdio\_ext.h}{int \_\_fsetlocking (FILE *stream, int type)}
+  Specifica o richiede a seconda del valore di \param{type} la modalità in cui
+  le operazioni di I/O su \param{stream} vengono effettuate rispetto
+  all'acquisizione implicita del blocco sullo stream.
 
+  \bodydesc{Restituisce lo stato di locking interno dello stream con uno dei
+  valori \macro{FSETLOCKING\_INTERNAL} o \macro{FSETLOCKING\_BYCALLER}.}
+\end{prototype}
 
-\subsection{Dettagli dell'implementazione}
-\label{sec:file_stream_details}
-
-
-\subsection{File temporanei}
-\label{sec:file_temp_file}
-
-
-\subsection{Efficienza}
-\label{sec:file_stream_efficiency}
-
+La funzione imposta o legge lo stato della modalità di operazione di uno stream
+nei confronti del locking a seconda del valore specificato con \param{type},
+che può essere uno dei seguenti:
+\begin{basedescript}{\desclabelwidth{4.0cm}}
+\item[\macro{FSETLOCKING\_INTERNAL}] Lo stream userà da ora in poi il blocco
+  implicito predefinito.
+\item[\macro{FSETLOCKING\_BYCALLER}] Al ritorno della funzione sarà l'utente a
+  dover gestire da solo il locking dello stream.
+\item[\macro{FSETLOCKING\_QUERY}] Restituisce lo stato corrente della modalità
+  di blocco dello stream.
+\end{basedescript}
+
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "gapil"
+%%% End: