%% filestd.tex
%%
-%% Copyright (C) 2000-2004 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2005 Simone Piccardi. Permission is granted to
%% copy, distribute and/or modify this document under the terms of the GNU Free
%% Documentation License, Version 1.1 or any later version published by the
-%% Free Software Foundation; with the Invariant Sections being "Prefazione",
+%% Free Software Foundation; with the Invariant Sections being "Un preambolo",
%% with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the
%% license is included in the section entitled "GNU Free Documentation
%% License".
nessuna forma di bufferizzazione per ottimizzare le operazioni di I/O.
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
+dimensioni del blocco di dati (l'argomento \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
\index{file!stream|)}
-\subsection{Gli oggetti \ctyp{FILE}}
+\subsection{Gli oggetti \type{FILE}}
\label{sec:file_FILE}
+
Per ragioni storiche la struttura di dati che rappresenta uno stream è stata
-chiamata \ctyp{FILE}, questi oggetti sono creati dalle funzioni di libreria e
+chiamata \type{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 (che sono dei \textsl{tipi opachi}\index{tipo!opaco}) ma
-usare sempre puntatori del tipo \ctyp{FILE *} ottenuti dalla libreria stessa
+usare sempre puntatori del tipo \texttt{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 variabili di questo tipo, che diventa accessibile
+come argomenti solo variabili di questo tipo, che diventa accessibile
includendo l'header file \file{stdio.h}.
sullo schermo.
\end{basedescript}
-Nelle \acr{glibc} \var{stdin}, \var{stdout} e \var{stderr} sono
-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:
-\includecodesnip{listati/redir_stdout.c}
-ma in altri sistemi queste variabili possono essere definite da macro, e
-se si hanno problemi di portabilità e si vuole essere sicuri, diventa
-opportuno usare la funzione \func{freopen}.
+Nelle \acr{glibc} \var{stdin}, \var{stdout} e \var{stderr} sono effettivamente
+tre variabili di tipo \type{FILE}\texttt{ *} che possono essere usate come
+tutte le altre, ad esempio si può effettuare una redirezione dell'output di un
+programma con il semplice codice: \includecodesnip{listati/redir_stdout.c} ma
+in altri sistemi queste variabili possono essere definite da macro, e se si
+hanno problemi di portabilità e si vuole essere sicuri, diventa opportuno
+usare la funzione \func{freopen}.
\subsection{Le modalità di bufferizzazione}
Per questo motivo tutte le implementazioni delle librerie standard
mantengono per ogni stream almeno due flag all'interno dell'oggetto
-\ctyp{FILE}, il flag di \textit{end-of-file}, che segnala che si è
+\type{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 \funcd{feof} e
meccanismo visto in sez.~\ref{sec:proc_var_passing}; per questo motivo se
si passa un'espressione si possono avere effetti indesiderati.
-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 nel tipo di argomento).
+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 argomento ad un altra funzione (e non si hanno i problemi accennati in
+precedenza nel tipo di argomento).
Le tre funzioni restituiscono tutte un \ctyp{unsigned char} convertito
ad \ctyp{int} (si usa \ctyp{unsigned char} in modo da evitare
fine del file il valore di ritorno è \val{EOF}.}
\end{functions}
-Tutte queste funzioni scrivono sempre un byte alla volta, anche se
-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
-è \val{EOF}.
+Tutte queste funzioni scrivono sempre un byte alla volta, anche se prendono
+come argomento 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 è \val{EOF}.
Come nel caso dell'I/O binario con \func{fread} e \func{fwrite} le \acr{glibc}
provvedono come estensione, per ciascuna delle funzioni precedenti,
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}\index{buffer overflow}, con sovrascrittura della memoria del
+ overflow}\itindex{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
-infatti inviare una stringa sufficientemente lunga ed opportunamente
-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
-che lancia una shell).
+Questa è una delle vulnerabilità più sfruttate per guadagnare accessi non
+autorizzati al sistema (i cosiddetti \textit{exploit}), basta infatti inviare
+una stringa sufficientemente lunga ed opportunamente forgiata per
+sovrascrivere gli indirizzi di ritorno nello \itindex{stack} 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 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
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
+argomento 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
+locale); come secondo argomento 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
-\index{\textit{value~result~argument}}\textit{value result argument}, passando
-dei puntatori anziché i valori delle variabili, secondo la tecnica spiegata in
+dimensione ed il nuovo puntatore vengono restituiti indietro (si noti infatti
+come per entrambi gli argomenti si siano usati dei
+\itindex{value~result~argument}\textit{value result argument}, passando dei
+puntatori anziché i valori delle variabili, secondo la tecnica spiegata in
sez.~\ref{sec:proc_var_passing}).
-Se si passa alla funzione l'indirizzo di un puntatore impostato a \val{NULL}
-e \var{*n} è zero, la funzione provvede da sola all'allocazione della memoria
+Se si passa alla funzione l'indirizzo di un puntatore impostato a \val{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:
-\includecodesnip{listati/getline.c}
-e per evitare memory leak\index{memory leak} occorre ricordarsi di liberare
-\var{ptr} con una \func{free}.
+essere il seguente:
+\includecodesnip{listati/getline.c}
+e per evitare \textit{memory leak}\itindex{memory~leak} occorre ricordarsi di
+liberare \var{ptr} con una \func{free}.
Il valore di ritorno della funzione indica il numero di caratteri letti
dallo stream (quindi compreso il newline, ma non lo zero di
\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
+\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}, con conseguente sovrascrittura di altre variabili e
-possibili \textit{buffer overflow}\index{buffer overflow}; per questo motivo
+possibili \textit{buffer overflow}\itindex{buffer~overflow}; per questo motivo
si consiglia l'uso dell'alternativa \funcd{snprintf}, il cui prototipo è:
\begin{prototype}{stdio.h}
{snprintf(char *str, size\_t size, const char *format, ...)}
La parte più complessa delle funzioni di scrittura formattata è il formato
della stringa \param{format} che indica le conversioni da fare, e da cui
-deriva anche il numero dei parametri che dovranno essere passati a seguire (si
-noti come tutte queste funzioni siano \textit{variadic}\index{variadic},
+deriva anche il numero degli argomenti che dovranno essere passati a seguire
+(si noti come tutte queste funzioni siano \textit{variadic}\index{variadic},
prendendo un numero di argomenti variabile che dipende appunto da quello che
si è specificato in \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
+si vogliono passare ad una funzione di stampa, passando direttamente la lista
+tramite l'argomento \param{ap}. Per poter far questo ovviamente la lista degli
+argomenti dovrà essere opportunamente trattata (l'argomento è esaminato in
sez.~\ref{sec:proc_variadic}), e dopo l'esecuzione della funzione l'argomento
\param{ap} non sarà più utilizzabile (in generale dovrebbe essere eseguito un
\code{va\_end(ap)} ma in Linux questo non è necessario).
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\index{buffer overflow}.
+\noindent in modo da evitare possibili buffer
+overflow\itindex{buffer~overflow}.
Per eliminare alla radice questi problemi, le \acr{glibc} supportano una
\bodydesc{Le funzioni ritornano il numero di caratteri stampati.}
\end{functions}
-Entrambe le funzioni prendono come parametro \param{strptr} che deve essere
+
+Entrambe le funzioni prendono come argomento \param{strptr} che deve essere
l'indirizzo di un puntatore ad una stringa di caratteri, in cui verrà
restituito (si ricordi quanto detto in sez.~\ref{sec:proc_var_passing} a
-proposito dei \index{\textit{value~result~argument}}\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\index{memory leak}.
+proposito dei \itindex{value~result~argument}\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 \textit{memory
+ leak}\itindex{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
\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.
+ conversione memorizzando il risultato negli argomenti seguenti.
\funcdecl{int fscanf(FILE *stream, const char *format, ...)} Analoga alla
precedente, ma effettua la scansione su \param{stream}.
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
+questo argomento è 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
+separazione (che possono essere spazi, tabulatori, virgole ecc.), 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}.
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 file di
- dispositivo\index{file!di dispositivo}, non è scontato che questo sia sempre
+ dispositivo\index{file!di~dispositivo}, non è scontato che questo sia sempre
vero.}
In GNU/Linux ed in generale in ogni sistema unix-like la posizione nel file è
rispetto al record corrente).
Tutto questo comporta la presenza di diverse funzioni che eseguono
-sostanzialmente le stesse operazioni, ma usano parametri di tipo diverso. Le
+sostanzialmente le stesse operazioni, ma usano argomenti di tipo diverso. Le
funzioni tradizionali usate per il riposizionamento della posizione in uno
stream sono \funcd{fseek} e \funcd{rewind} i cui prototipi sono:
\begin{functions}
\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
+descriptor, e gli argomenti, a parte il tipo, hanno lo stesso significato; in
particolare \param{whence} assume gli stessi valori già visti in
sez.~\ref{sec:file_lseek}. La funzione restituisce 0 in caso di successo e -1
in caso di errore. La funzione \func{rewind} riporta semplicemente la
\const{\_IOFBF} & \textit{fully buffered}\\
\hline
\end{tabular}
- \caption{Valori del parametro \param{mode} di \func{setvbuf}
- per l'impostazione delle modalità di bufferizzazione.}
+ \caption{Valori dell'argomento \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
-\val{NULL} per \param{buf} e la funzione ignorerà il parametro \param{size}
+\val{NULL} per \param{buf} e la funzione ignorerà l'argomento \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 tab.~\ref{tab:file_stream_buf_mode}. Qualora si