%% 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 "Un preambolo",
%% 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 "Un preambolo",
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
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
sono gestibili a basso livello con l'interfaccia standard unix, che ricorre
direttamente alle system call messe a disposizione dal kernel.
sono gestibili a basso livello con l'interfaccia standard unix, che ricorre
direttamente alle system call messe a disposizione dal kernel.
ANSI C, che invece sono realizzate attraverso opportune funzioni di libreria,
queste, insieme alle altre funzioni definite dallo standard, vengono a
costituire il nucleo\footnote{queste funzioni sono state implementate la prima
ANSI C, che invece sono realizzate attraverso opportune funzioni di libreria,
queste, insieme alle altre funzioni definite dallo standard, vengono a
costituire il nucleo\footnote{queste funzioni sono state implementate la prima
basso livello, che non provvede nessuna forma di formattazione dei dati e
nessuna forma di bufferizzazione per ottimizzare le operazioni di I/O.
basso livello, che non provvede nessuna forma di formattazione dei dati e
nessuna forma di bufferizzazione per ottimizzare le operazioni di I/O.
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 \struct{stat}), che di norma corrispondono alle
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 \struct{stat}), che di norma corrispondono alle
Se il programmatore non si cura di effettuare le operazioni in blocchi di
dimensioni adeguate, le prestazioni sono inferiori. La caratteristica
Se il programmatore non si cura di effettuare le operazioni in blocchi di
dimensioni adeguate, le prestazioni sono inferiori. La caratteristica
gestione dei dettagli della bufferizzazione e all'esecuzione delle operazioni
di lettura e scrittura in blocchi di dimensioni appropriate all'ottenimento
della massima efficienza.
Per questo motivo l'interfaccia viene chiamata anche interfaccia dei
gestione dei dettagli della bufferizzazione e all'esecuzione delle operazioni
di lettura e scrittura in blocchi di dimensioni appropriate all'ottenimento
della massima efficienza.
Per questo motivo l'interfaccia viene chiamata anche interfaccia dei
dei dettagli della comunicazione con il tipo di hardware sottostante
(come nel caso della dimensione dei blocchi del filesystem), ed un file
dei dettagli della comunicazione con il tipo di hardware sottostante
(come nel caso della dimensione dei blocchi del filesystem), ed un file
cui il nome \textit{stream}) di dati.
A parte i dettagli legati alla gestione delle operazioni di lettura e
cui il nome \textit{stream}) di dati.
A parte i dettagli legati alla gestione delle operazioni di lettura 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
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
Per questo motivo gli utenti non devono mai utilizzare direttamente o allocare
queste strutture (che sono dei \index{tipo!opaco} \textsl{tipi opachi}) ma
usare sempre puntatori del tipo \texttt{FILE *} ottenuti dalla libreria stessa
Per questo motivo gli utenti non devono mai utilizzare direttamente o allocare
queste strutture (che sono dei \index{tipo!opaco} \textsl{tipi opachi}) ma
usare sempre puntatori del tipo \texttt{FILE *} ottenuti dalla libreria stessa
di stream). Tutte le funzioni della libreria che operano sui file accettano
come argomenti solo variabili di questo tipo, che diventa accessibile
includendo l'header file \file{stdio.h}.
di stream). Tutte le funzioni della libreria che operano sui file accettano
come argomenti solo variabili di questo tipo, che diventa accessibile
includendo l'header file \file{stdio.h}.
-\item[\var{FILE *stdout}] Lo \textit{standard output} cioè lo stream su
- cui il processo invia ordinariamente i dati in uscita. Normalmente è
+\item[\var{FILE *stdout}] Lo \textit{standard output} cioè lo stream su
+ cui il processo invia ordinariamente i dati in uscita. Normalmente è
-\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
+\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{basedescript}
Nelle \acr{glibc} \var{stdin}, \var{stdout} e \var{stderr} sono effettivamente
tre variabili di tipo \type{FILE}\texttt{ *} che possono essere usate come
sullo schermo.
\end{basedescript}
Nelle \acr{glibc} \var{stdin}, \var{stdout} e \var{stderr} sono effettivamente
tre variabili di tipo \type{FILE}\texttt{ *} che possono essere usate come
programma con il semplice codice: \includecodesnip{listati/redir_stdout.c} ma
in altri sistemi queste variabili possono essere definite da macro, e se si
programma con il semplice codice: \includecodesnip{listati/redir_stdout.c} ma
in altri sistemi queste variabili possono essere definite da macro, e se si
-La bufferizzazione è una delle caratteristiche principali dell'interfaccia
-degli stream; lo scopo è quello di ridurre al minimo il numero di system call
+La bufferizzazione è una delle caratteristiche principali dell'interfaccia
+degli stream; lo scopo è quello di ridurre al minimo il numero di system call
-funzionalità è assicurata automaticamente dalla libreria, ma costituisce anche
-uno degli aspetti più comunemente fraintesi, in particolare per quello che
+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 di uno stream normalmente vengono
riguarda l'aspetto della scrittura dei dati sul file.
I caratteri che vengono scritti su di uno stream normalmente vengono
viene usualmente chiamata \textsl{scaricamento} dei dati, dal termine
inglese \textit{flush}.} tutte le volte che il buffer viene riempito, in
maniera asincrona rispetto alla scrittura. Un comportamento analogo avviene
viene usualmente chiamata \textsl{scaricamento} dei dati, dal termine
inglese \textit{flush}.} tutte le volte che il buffer viene riempito, in
maniera asincrona rispetto alla scrittura. 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
+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.
Per lo stesso motivo, in tutte le situazioni in cui si sta facendo
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.
Per lo stesso motivo, in tutte le situazioni in cui si sta facendo
-dell'input/output interattivo, bisognerà tenere presente le caratteristiche
-delle operazioni di scaricamento dei dati, poiché non è detto che ad una
+dell'input/output interattivo, bisognerà tenere presente le caratteristiche
+delle operazioni di scaricamento dei dati, poiché non è detto che ad una
caratteri vengono trasmessi direttamente al file non appena possibile
(effettuando immediatamente una \func{write}).
\item \textit{line buffered}: in questo caso i caratteri vengono
caratteri vengono trasmessi direttamente al file non appena possibile
(effettuando immediatamente una \func{write}).
\item \textit{line buffered}: in questo caso i caratteri vengono
-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ù
+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ù
-modalità \textit{line buffered} quando sono associati ad un terminale (od
-altro dispositivo interattivo) ed in modalità \textit{fully buffered}
+modalità \textit{line buffered} quando sono associati ad un terminale (od
+altro dispositivo interattivo) ed in modalità \textit{fully buffered}
altrimenti.
Il comportamento specificato per standard input e standard output vale anche
per tutti i nuovi stream aperti da un processo; la selezione comunque avviene
altrimenti.
Il comportamento specificato per standard input e standard output vale anche
per tutti i nuovi stream aperti da un processo; la selezione comunque avviene
-La modalità \textit{line buffered} è quella che necessita di maggiori
-chiarimenti e attenzioni per quel che concerne il suo funzionamento. Come già
+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 \textsl{a capo} (\textit{newline}); questo
accennato nella descrizione, \emph{di norma} i dati vengono inviati al kernel
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
+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
anche prima che sia stato inviato un carattere di \textit{newline}.
Un secondo punto da tenere presente, particolarmente quando si ha a che fare
tutti i buffer degli stream in scrittura.
In sez.~\ref{sec:file_buffering_ctrl} vedremo come la libreria definisca delle
tutti i buffer degli stream in scrittura.
In sez.~\ref{sec:file_buffering_ctrl} vedremo come la libreria definisca delle
Le funzioni che si possono usare per aprire uno stream sono solo tre:
\funcd{fopen}, \funcd{fdopen} e \funcd{freopen},\footnote{\func{fopen} e
Le funzioni che si possono usare per aprire uno stream sono solo tre:
\funcd{fopen}, \funcd{fdopen} e \funcd{freopen},\footnote{\func{fopen} e
Associa uno stream al file descriptor \param{fildes}.
\funcdecl{FILE *freopen(const char *path, const char *mode, FILE *stream)}
Apre il file specificato da \param{path} associandolo allo stream
Associa uno stream al file descriptor \param{fildes}.
\funcdecl{FILE *freopen(const char *path, const char *mode, FILE *stream)}
Apre il file specificato da \param{path} associandolo allo stream
- \val{NULL} in caso di errore, in tal caso \var{errno} assumerà il valore
- ricevuto dalla funzione sottostante di cui è fallita l'esecuzione.
+ \val{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
e tre le funzioni, quelli \func{open} per \func{fopen}, quelli di
Gli errori pertanto possono essere quelli di \func{malloc} per tutte
e tre le funzioni, quelli \func{open} per \func{fopen}, quelli di
-Normalmente la funzione che si usa per aprire uno stream è \func{fopen},
-essa apre il file specificato nella modalità specificata da
-\param{mode}, che è una stringa che deve iniziare con almeno uno dei
+Normalmente la funzione che si usa per aprire uno stream è \func{fopen},
+essa apre il file specificato nella modalità specificata da
+\param{mode}, che è una stringa che deve iniziare con almeno uno dei
valori indicati in tab.~\ref{tab:file_fopen_mode} (sono possibili varie
estensioni che vedremo in seguito).
valori indicati in tab.~\ref{tab:file_fopen_mode} (sono possibili varie
estensioni che vedremo in seguito).
% \hline
\texttt{w} & Il file viene aperto e troncato a lunghezza nulla (o
creato se non esiste), l'accesso viene posto in sola
% \hline
\texttt{w} & Il file viene aperto e troncato a lunghezza nulla (o
creato se non esiste), l'accesso viene posto in sola
\texttt{w+}& Il file viene aperto e troncato a lunghezza nulla (o
creato se non esiste), l'accesso viene posto in scrittura e
\texttt{w+}& Il file viene aperto e troncato a lunghezza nulla (o
creato se non esiste), l'accesso viene posto in scrittura e
% \hline
\texttt{a} & Il file viene aperto (o creato se non esiste) in
\itindex{append~mode} \textit{append mode}, l'accesso viene
% \hline
\texttt{a} & Il file viene aperto (o creato se non esiste) in
\itindex{append~mode} \textit{append mode}, l'accesso viene
\itindex{append~mode} \textit{append mode}, l'accesso viene
posto in lettura e scrittura.\\
\hline
\itindex{append~mode} \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à. \\
+ \texttt{b} & Specifica che il file è binario, non ha alcun effetto. \\
+ \texttt{x} & L'apertura fallisce se il file esiste già. \\
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
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
Le \acr{glibc} supportano alcune estensioni, queste devono essere sempre
indicate dopo aver specificato il \param{mode} con uno dei valori di
tab.~\ref{tab:file_fopen_mode}. L'uso del carattere \texttt{x} serve per
Le \acr{glibc} supportano alcune estensioni, queste devono essere sempre
indicate dopo aver specificato il \param{mode} con uno dei valori di
tab.~\ref{tab:file_fopen_mode}. L'uso del carattere \texttt{x} serve per
-evitare di sovrascrivere un file già esistente (è analoga all'uso
-dell'opzione \const{O\_EXCL} in \func{open}), se il file specificato già
+evitare di sovrascrivere un file già esistente (è analoga all'uso
+dell'opzione \const{O\_EXCL} in \func{open}), se il file specificato già
esiste e si aggiunge questo carattere a \param{mode} la \func{fopen}
fallisce.
Un'altra estensione serve a supportare la localizzazione, quando si
aggiunge a \param{mode} una stringa della forma \verb|",ccs=STRING"| il
esiste e si aggiunge questo carattere a \param{mode} la \func{fopen}
fallisce.
Un'altra estensione serve a supportare la localizzazione, quando si
aggiunge a \param{mode} una stringa della forma \verb|",ccs=STRING"| il
e \func{fopen} marca il file per l'uso dei caratteri estesi e abilita le
opportune funzioni di conversione in lettura e scrittura.
Nel caso si usi \func{fdopen} i valori specificati da \param{mode} devono
e \func{fopen} marca il file per l'uso dei caratteri estesi e abilita le
opportune funzioni di conversione in lettura e scrittura.
Nel caso si usi \func{fdopen} i valori specificati da \param{mode} devono
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 sez.~\ref{sec:file_io}) sono cancellate. Il
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 sez.~\ref{sec:file_io}) sono cancellate. Il
I nuovi file saranno creati secondo quanto visto in
sez.~\ref{sec:file_ownership_management} ed avranno i permessi di accesso
I nuovi file saranno creati secondo quanto visto in
sez.~\ref{sec:file_ownership_management} ed avranno i permessi di accesso
\val{0666}) modificato secondo il valore di \itindex{umask} \textit{umask} per
il processo (si veda sez.~\ref{sec:file_perm_management}).
\val{0666}) modificato secondo il valore di \itindex{umask} \textit{umask} per
il processo (si veda sez.~\ref{sec:file_perm_management}).
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
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
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 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 volta aperto lo stream, si può cambiare la modalità di bufferizzazione
-(si veda sez.~\ref{sec:file_buffering_ctrl}) fintanto che non si è effettuato
+Una volta aperto lo stream, si può cambiare la modalità di bufferizzazione
+(si veda sez.~\ref{sec:file_buffering_ctrl}) fintanto che non si è effettuato
\begin{prototype}{stdio.h}{int fclose(FILE *stream)}
Chiude lo stream \param{stream}.
\bodydesc{Restituisce 0 in caso di successo e \val{EOF} in caso di errore,
nel qual caso imposta \var{errno} a \errval{EBADF} se il file descriptor
\begin{prototype}{stdio.h}{int fclose(FILE *stream)}
Chiude lo stream \param{stream}.
\bodydesc{Restituisce 0 in caso di successo e \val{EOF} in caso di errore,
nel qual caso imposta \var{errno} a \errval{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
+ indicato da \param{stream} non è valido, o uno dei valori specificati
+ dalla sottostante funzione che è fallita (\func{close}, \func{write} o
\func{fflush}).}
\end{prototype}
La funzione effettua lo scarico di tutti i dati presenti nei buffer di uscita
e scarta tutti i dati in ingresso; se era stato allocato un buffer per lo
\func{fflush}).}
\end{prototype}
La funzione effettua lo scarico di tutti i dati presenti nei buffer di uscita
e scarta tutti i dati in ingresso; se era stato allocato un buffer per lo
una \func{sync} (vedi sez.~\ref{sec:file_sync}).
Linux supporta anche una altra funzione, \funcd{fcloseall}, come estensione
GNU implementata dalle \acr{glibc}, accessibile avendo definito
una \func{sync} (vedi sez.~\ref{sec:file_sync}).
Linux supporta anche una altra funzione, \funcd{fcloseall}, come estensione
GNU implementata dalle \acr{glibc}, accessibile avendo definito
\begin{prototype}{stdio.h}{int fcloseall(void)}
Chiude tutti gli stream.
\bodydesc{Restituisce 0 se non ci sono errori ed \val{EOF} altrimenti.}
\end{prototype}
\noindent la funzione esegue lo scarico dei dati bufferizzati in uscita
\begin{prototype}{stdio.h}{int fcloseall(void)}
Chiude tutti gli stream.
\bodydesc{Restituisce 0 se non ci sono errori ed \val{EOF} altrimenti.}
\end{prototype}
\noindent la funzione esegue lo scarico dei dati bufferizzati in uscita
-e scarta quelli in ingresso, chiudendo tutti i file. Questa funzione è
-provvista solo per i casi di emergenza, quando si è verificato un errore
+e scarta quelli in ingresso, chiudendo tutti i file. Questa funzione è
+provvista solo per i casi di emergenza, quando si è verificato un errore
ed il programma deve essere abortito, ma si vuole compiere qualche altra
operazione dopo aver chiuso i file e prima di uscire (si ricordi quanto
visto in sez.~\ref{sec:proc_exit}).
ed il programma deve essere abortito, ma si vuole compiere qualche altra
operazione dopo aver chiuso i file e prima di uscire (si ricordi quanto
visto in sez.~\ref{sec:proc_exit}).
-scrittura sui file. Sono infatti previste ben tre diverse modalità
-modalità di input/output non formattato:
+scrittura sui file. Sono infatti previste ben tre diverse modalità
+modalità di input/output non formattato:
\begin{enumerate*}
\item\textsl{binario} in cui legge/scrive un blocco di dati alla
volta, vedi sez.~\ref{sec:file_binary_io}.
\begin{enumerate*}
\item\textsl{binario} in cui legge/scrive un blocco di dati alla
volta, vedi sez.~\ref{sec:file_binary_io}.
\item\textsl{di linea} in cui si legge/scrive una linea alla volta (terminata
dal carattere di newline \verb|'\n'|), vedi sez.~\ref{sec:file_line_io}.
\end{enumerate*}
\item\textsl{di linea} in cui si legge/scrive una linea alla volta (terminata
dal carattere di newline \verb|'\n'|), vedi sez.~\ref{sec:file_line_io}.
\end{enumerate*}
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 \ctyp{int}) \val{EOF}\footnote{la costante deve essere
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 \ctyp{int}) \val{EOF}\footnote{la costante deve essere
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 impostato in
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 impostato in
Per questo motivo tutte le implementazioni delle librerie standard
mantengono per ogni stream almeno due flag all'interno dell'oggetto
Per questo motivo tutte le implementazioni delle librerie standard
mantengono per ogni stream almeno due flag all'interno dell'oggetto
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
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
i relativi flag sono impostati.}
\end{functions}
\noindent si tenga presente comunque che la lettura di questi flag segnala
i relativi flag sono impostati.}
\end{functions}
\noindent si tenga presente comunque che la lettura di questi flag segnala
qualunque operazione sullo stream, il controllo quindi deve essere effettuato
ogni volta che si chiama una funzione di libreria.
Entrambi i flag (di errore e di end-of-file) possono essere cancellati usando
qualunque operazione sullo stream, il controllo quindi deve essere effettuato
ogni volta che si chiama una funzione di libreria.
Entrambi i flag (di errore e di end-of-file) possono essere cancellati usando
\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 funzione una volta che si sia identificata e
\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 funzione una volta che si sia identificata e
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 sez.~\ref{sec:file_stream_thread}).
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 sez.~\ref{sec:file_stream_thread}).
-lettura dei dati da un buffer verso un file e viceversa. In generale questa è
-la modalità che si usa quando si ha a che fare con dati non formattati. Le due
+lettura dei dati da un buffer verso un file e viceversa. In generale questa è
+la modalità che si usa quando si ha a che fare con dati non formattati. Le due
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
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
elementi) con una chiamata del tipo:
\includecodesnip{listati/WriteVect.c}
in questo caso devono essere specificate le dimensioni di ciascun
elemento ed il numero di quelli che si vogliono scrivere. Un secondo
elementi) con una chiamata del tipo:
\includecodesnip{listati/WriteVect.c}
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:
+caso è invece quello in cui si vuole trasferire su file una struttura;
+si avrà allora una chiamata tipo:
\includecodesnip{listati/WriteStruct.c}
in cui si specifica la dimensione dell'intera struttura ed un solo
elemento.
\includecodesnip{listati/WriteStruct.c}
in cui si specifica la dimensione dell'intera struttura ed un solo
elemento.
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 impostata alla fine del file (e non a quella corrispondente
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 impostata alla fine del file (e non a quella corrispondente
In caso di errore (o fine del file per \func{fread}) entrambe le
funzioni restituiscono il numero di oggetti effettivamente letti o
In caso di errore (o fine del file per \func{fread}) entrambe le
funzioni restituiscono il numero di oggetti effettivamente letti o
salvataggio dei dati, i dati memorizzati attraverso di esse presentano
lo svantaggio di dipendere strettamente dalla piattaforma di sviluppo
usata ed in genere possono essere riletti senza problemi solo dallo
salvataggio dei dati, i dati memorizzati attraverso di esse presentano
lo svantaggio di dipendere strettamente dalla piattaforma di sviluppo
usata ed in genere possono essere riletti senza problemi solo dallo
Infatti diversi compilatori possono eseguire ottimizzazioni diverse delle
strutture dati e alcuni compilatori (come il \cmd{gcc}) possono anche
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
+scegliere se ottimizzare l'occupazione di spazio, impacchettando più
+strettamente i dati, o la velocità inserendo opportuni \textit{padding} per
-altre incompatibilità si possono presentare quando entrano in gioco differenze
-di architettura hardware, come la dimensione del bus o la modalità di
+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
ordinamento dei bit o il formato delle variabili in floating point.
Per questo motivo quando si usa l'input/output binario occorre sempre prendere
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.
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.
trasferisce un carattere alla volta. Le funzioni per la lettura a
caratteri sono tre, \funcd{fgetc}, \funcd{getc} e \funcd{getchar}, i
rispettivi prototipi sono:
trasferisce un carattere alla volta. Le funzioni per la lettura a
caratteri sono tre, \funcd{fgetc}, \funcd{getc} e \funcd{getchar}, i
rispettivi prototipi sono:
\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
\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
\end{functions}
A parte \func{getchar}, che si usa in genere per leggere un carattere da
tastiera, le altre due funzioni sono sostanzialmente equivalenti. La
\end{functions}
A parte \func{getchar}, che si usa in genere per leggere un carattere da
tastiera, le altre due funzioni sono sostanzialmente equivalenti. La
-le si passa come argomento, infatti \param{stream} può essere valutato
-più volte nell'esecuzione, e non viene passato in copia con il
+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 sez.~\ref{sec:proc_var_passing}; per questo motivo se
si passa un'espressione si possono avere effetti indesiderati.
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
+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
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
positivo, tranne in caso di errore o fine del file.
Nelle estensioni GNU che provvedono la localizzazione sono definite tre
funzioni equivalenti alle precedenti, \funcd{getwc}, \funcd{fgetwc} e
\funcd{getwchar}, che invece di un carattere di un byte restituiscono un
positivo, tranne in caso di errore o fine del file.
Nelle estensioni GNU che provvedono la localizzazione sono definite tre
funzioni equivalenti alle precedenti, \funcd{getwc}, \funcd{fgetwc} e
\funcd{getwchar}, che invece di un carattere di un byte restituiscono un
\funcdecl{wint\_t getwchar(void)} Equivalente a \code{getwc(stdin)}.
\bodydesc{Tutte queste funzioni leggono un carattere alla volta, in
\funcdecl{wint\_t getwchar(void)} Equivalente a \code{getwc(stdin)}.
\bodydesc{Tutte queste funzioni leggono un carattere alla volta, in
\funcdecl{int putchar(int c)} Equivalente a \code{putc(stdout)}.
\bodydesc{Le funzioni scrivono sempre un carattere alla volta, il cui
valore viene restituito in caso di successo; in caso di errore o
\funcdecl{int putchar(int c)} Equivalente a \code{putc(stdout)}.
\bodydesc{Le funzioni scrivono sempre un carattere alla volta, il cui
valore viene restituito in caso di successo; in caso di errore o
\end{functions}
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
\end{functions}
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}.
+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,
Come nel caso dell'I/O binario con \func{fread} e \func{fwrite} le \acr{glibc}
provvedono come estensione, per ciascuna delle funzioni precedenti,
-un'ulteriore funzione, il cui nome è ottenuto aggiungendo un
-\code{\_unlocked}, che esegue esattamente le stesse operazioni, evitando però
+un'ulteriore funzione, il cui nome è ottenuto aggiungendo un
+\code{\_unlocked}, che esegue esattamente le stesse operazioni, evitando però
-una variabile di tipo \ctyp{int}; il loro uso è deprecato in favore dell'uso
-di \func{fread} e \func{fwrite}, in quanto non è possibile distinguere il
+una variabile di tipo \ctyp{int}; il loro uso è deprecato in favore dell'uso
+di \func{fread} e \func{fwrite}, in quanto non è possibile distinguere il
\textit{parsing} in cui si analizza il testo; in questo contesto diventa utile
poter analizzare il carattere successivo da uno stream senza estrarlo
\textit{parsing} in cui si analizza il testo; in questo contesto diventa utile
poter analizzare il carattere successivo da uno stream senza estrarlo
-Nel nostro caso questo tipo di comportamento può essere realizzato prima
-leggendo il carattere, e poi rimandandolo indietro, cosicché ridiventi
+Nel nostro caso questo tipo di comportamento può essere realizzato prima
+leggendo il carattere, e poi rimandandolo indietro, cosicché ridiventi
\begin{prototype}{stdio.h}{int ungetc(int c, FILE *stream)}
Rimanda indietro il carattere \param{c}, con un cast a \ctyp{unsigned
char}, sullo stream \param{stream}.
\begin{prototype}{stdio.h}{int ungetc(int c, FILE *stream)}
Rimanda indietro il carattere \param{c}, con un cast a \ctyp{unsigned
char}, sullo stream \param{stream}.
quello che fa la \acr{glibc}, che richiede che avvenga un'altra
operazione fra due \func{ungetc} successive.
quello che fa la \acr{glibc}, che richiede che avvenga un'altra
operazione fra due \func{ungetc} successive.
-Non è necessario che il carattere che si manda indietro sia l'ultimo che
-si è letto, e non è necessario neanche avere letto nessun carattere
-prima di usare \func{ungetc}, ma di norma la funzione è intesa per
+Non è necessario che il carattere che si manda indietro sia l'ultimo che
+si è letto, e non è necessario neanche avere letto nessun carattere
+prima di usare \func{ungetc}, ma di norma la funzione è intesa per
essere usata per rimandare indietro l'ultimo carattere letto.
Nel caso \param{c} sia un \val{EOF} la funzione non fa nulla, e
essere usata per rimandare indietro l'ultimo carattere letto.
Nel caso \param{c} sia un \val{EOF} la funzione non fa nulla, e
-Se si è alla fine del file si può comunque rimandare indietro un
-carattere, il flag di end-of-file verrà automaticamente cancellato
-perché c'è un nuovo carattere disponibile che potrà essere riletto
+Se si è alla fine del file si può comunque rimandare indietro un
+carattere, il flag di end-of-file verrà automaticamente cancellato
+perché c'è un nuovo carattere disponibile che potrà essere riletto
-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 è anche quella 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 è anche quella che presenta le
+caratteristiche più controverse.
Le funzioni previste dallo standard ANSI C per leggere una linea sono
sostanzialmente due, \funcd{gets} e \funcd{fgets}, i cui rispettivi
Le funzioni previste dallo standard ANSI C per leggere una linea sono
sostanzialmente due, \funcd{gets} e \funcd{fgets}, i cui rispettivi
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
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
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} \textit{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
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} \textit{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
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}
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
+caratteri, ma la stringa sarà sempre terminata correttamente con uno zero
+finale; sarà possibile leggere i rimanenti caratteri in una chiamata
messaggi sullo standard output; la funzione prende una stringa terminata da
uno zero ed aggiunge automaticamente il ritorno a capo. La differenza con
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
+\func{fputs} (a parte la possibilità di specificare un file diverso da
+\var{stdout}) è che quest'ultima non aggiunge il newline, che deve essere
-terminatore della stringa, newline) è espresso in termini di caratteri estesi
-anziché di normali caratteri ASCII.
+terminatore della stringa, newline) è espresso in termini di caratteri estesi
+anziché di normali caratteri ASCII.
Come per l'I/O binario e quello a caratteri, anche per l'I/O di linea le
\acr{glibc} supportano una serie di altre funzioni, estensioni di tutte quelle
illustrate finora (eccetto \func{gets} e \func{puts}), che eseguono
Come per l'I/O binario e quello a caratteri, anche per l'I/O di linea le
\acr{glibc} supportano una serie di altre funzioni, estensioni di tutte quelle
illustrate finora (eccetto \func{gets} e \func{puts}), che eseguono
implicito dello stream (vedi sez.~\ref{sec:file_stream_thread}). Come per le
altre forma di I/O, dette funzioni hanno lo stesso nome della loro analoga
normale, con l'aggiunta dell'estensione \code{\_unlocked}.
Come abbiamo visto, le funzioni di lettura per l'input/output di linea
implicito dello stream (vedi sez.~\ref{sec:file_stream_thread}). Come per le
altre forma di I/O, dette funzioni hanno lo stesso nome della loro analoga
normale, con l'aggiunta dell'estensione \code{\_unlocked}.
Come abbiamo visto, le funzioni di lettura per l'input/output di linea
-previste dallo standard ANSI C presentano svariati inconvenienti. Benché
-\func{fgets} non abbia i gravissimi problemi di \func{gets}, può
+previste dallo standard ANSI C presentano svariati inconvenienti. Benché
+\func{fgets} non abbia i gravissimi problemi di \func{gets}, può
comunque dare risultati ambigui se l'input contiene degli zeri; questi
infatti saranno scritti sul buffer di uscita e la stringa in output
comunque dare risultati ambigui se l'input contiene degli zeri; questi
infatti saranno scritti sul buffer di uscita e la stringa in output
-apparirà come più corta dei byte effettivamente letti. Questa è una
-condizione che è sempre possibile controllare (deve essere presente un
+apparirà come più corta dei byte effettivamente letti. Questa è una
+condizione che è sempre possibile controllare (deve essere presente un
newline prima della effettiva conclusione della stringa presente nel
buffer), ma a costo di una complicazione ulteriore della logica del
programma. Lo stesso dicasi quando si deve gestire il caso di stringa
newline prima della effettiva conclusione della stringa presente nel
buffer), ma a costo di una complicazione ulteriore della logica del
programma. Lo stesso dicasi quando si deve gestire il caso di stringa
risolvere questi problemi. L'uso di queste funzioni deve essere attivato
definendo la macro \macro{\_GNU\_SOURCE} prima di includere \file{stdio.h}. La
prima delle due, \funcd{getline}, serve per leggere una linea terminata da un
risolvere questi problemi. L'uso di queste funzioni deve essere attivato
definendo la macro \macro{\_GNU\_SOURCE} prima di includere \file{stdio.h}. La
prima delle due, \funcd{getline}, serve per leggere una linea terminata da un
\begin{prototype}{stdio.h}
{ssize\_t getline(char **buffer, size\_t *n, FILE *stream)} Legge una linea
dal file \param{stream} copiandola sul buffer indicato da \param{buffer}
\begin{prototype}{stdio.h}
{ssize\_t getline(char **buffer, size\_t *n, FILE *stream)} Legge una linea
dal file \param{stream} copiandola sul buffer indicato da \param{buffer}
eventuale lunghezza eccessiva della stringa da leggere. Essa prende come primo
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
eventuale lunghezza eccessiva della stringa da leggere. Essa prende come primo
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
locale); come secondo argomento la funzione vuole l'indirizzo della variabile
contenente le dimensioni del buffer suddetto.
locale); come secondo argomento la funzione vuole l'indirizzo della variabile
contenente le dimensioni del buffer suddetto.
subito, altrimenti il buffer viene allargato usando \func{realloc} e la nuova
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
subito, altrimenti il buffer viene allargato usando \func{realloc} e la nuova
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
sez.~\ref{sec:proc_var_passing}).
Se si passa alla funzione l'indirizzo di un puntatore impostato a \val{NULL} e
sez.~\ref{sec:proc_var_passing}).
Se si passa alla funzione l'indirizzo di un puntatore impostato a \val{NULL} e
essere il seguente:
\includecodesnip{listati/getline.c}
e per evitare \itindex{memory~leak} \textit{memory leak} occorre ricordarsi di
essere il seguente:
\includecodesnip{listati/getline.c}
e per evitare \itindex{memory~leak} \textit{memory leak} occorre ricordarsi di
dallo stream (quindi compreso il newline, ma non lo zero di
terminazione); questo permette anche di distinguere eventuali zeri letti
dallo stream da quello inserito dalla funzione per terminare la linea.
dallo stream (quindi compreso il newline, ma non lo zero di
terminazione); questo permette anche di distinguere eventuali zeri letti
dallo stream da quello inserito dalla funzione per terminare la linea.
\begin{prototype}{stdio.h}
{ssize\_t getdelim(char **buffer, size\_t *n, int delim, FILE *stream)}
Identica a \func{getline} solo che usa \param{delim} al posto del
carattere di newline come separatore di linea.
\end{prototype}
\begin{prototype}{stdio.h}
{ssize\_t getdelim(char **buffer, size\_t *n, int delim, FILE *stream)}
Identica a \func{getline} solo che usa \param{delim} al posto del
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
+Il comportamento di \func{getdelim} è identico a quello di \func{getline} (che
+può essere implementata da questa passando \verb|'\n'| come valore di
-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é
+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.
L'output formattato viene eseguito con una delle 13 funzioni della famiglia
permette di stampare in maniera facile e veloce dati, tabelle e messaggi.
L'output formattato viene eseguito con una delle 13 funzioni della famiglia
\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
\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
sicurezza assoluta sulle dimensioni del risultato della stampa, eccedere le
dimensioni di \param{str}, con conseguente sovrascrittura di altre variabili e
possibili \itindex{buffer~overflow} \textit{buffer overflow}; per questo
motivo si consiglia l'uso dell'alternativa \funcd{snprintf}, il cui prototipo
sicurezza assoluta sulle dimensioni del risultato della stampa, eccedere le
dimensioni di \param{str}, con conseguente sovrascrittura di altre variabili e
possibili \itindex{buffer~overflow} \textit{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, ...)}
\begin{prototype}{stdio.h}
{snprintf(char *str, size\_t size, const char *format, ...)}
della stringa \param{format} che indica le conversioni da fare, e da cui
deriva anche il numero degli argomenti che dovranno essere passati a seguire
(si noti come tutte queste funzioni siano \index{variadic} \textit{variadic},
prendendo un numero di argomenti variabile che dipende appunto da quello che
della stringa \param{format} che indica le conversioni da fare, e da cui
deriva anche il numero degli argomenti che dovranno essere passati a seguire
(si noti come tutte queste funzioni siano \index{variadic} \textit{variadic},
prendendo un numero di argomenti variabile che dipende appunto da quello che
lettere minuscole e maiuscole.\\
\cmd{\%g},
\cmd{\%G} &\ctyp{double} & Stampano un numero in virgola mobile con la
lettere minuscole e maiuscole.\\
\cmd{\%g},
\cmd{\%G} &\ctyp{double} & Stampano un numero in virgola mobile con la
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
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
\val{-} & La conversione viene allineata a sinistra sul bordo del campo.\\
\val{' '}& Mette uno spazio prima di un numero con segno di valore
positivo.\\
\val{-} & La conversione viene allineata a sinistra sul bordo del campo.\\
\val{' '}& Mette uno spazio prima di un numero con segno di valore
positivo.\\
Il formato di una direttiva di conversione prevede una serie di possibili
elementi opzionali oltre al \cmd{\%} e allo specificatore di conversione. In
Il formato di una direttiva di conversione prevede una serie di possibili
elementi opzionali oltre al \cmd{\%} e allo specificatore di conversione. In
\end{center}
in cui tutti i valori tranne il \val{\%} e lo specificatore di conversione
sono opzionali (e per questo sono indicati fra parentesi quadre); si possono
\end{center}
in cui tutti i valori tranne il \val{\%} e lo specificatore di conversione
sono opzionali (e per questo sono indicati fra parentesi quadre); si possono
tab.~\ref{tab:file_format_flag}) che controllano il formato di stampa della
conversione,
\item uno specificatore di larghezza (un numero decimale), eventualmente
tab.~\ref{tab:file_format_flag}) che controllano il formato di stampa della
conversione,
\item uno specificatore di larghezza (un numero decimale), eventualmente
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}
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}
\cmd{l} & Una conversione intera corrisponde a un \ctyp{long} con o
senza segno, o il puntatore per il numero dei parametri \cmd{n}
\cmd{l} & Una conversione intera corrisponde a un \ctyp{long} con o
senza segno, o il puntatore per il numero dei parametri \cmd{n}
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}
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}
\noindent con queste funzioni diventa possibile selezionare gli argomenti che
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
\noindent con queste funzioni diventa possibile selezionare gli argomenti che
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
-\param{ap} non sarà più utilizzabile (in generale dovrebbe essere eseguito un
-\code{va\_end(ap)} ma in Linux questo non è necessario).
+\param{ap} non sarà più utilizzabile (in generale dovrebbe essere eseguito un
+\code{va\_end(ap)} ma in Linux questo non è necessario).
Come per \func{sprintf} anche per \func{vsprintf} esiste una analoga
\funcd{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)}
Come per \func{sprintf} anche per \func{vsprintf} esiste una analoga
\funcd{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)}
restituito (si ricordi quanto detto in sez.~\ref{sec:proc_var_passing} a
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
restituito (si ricordi quanto detto in sez.~\ref{sec:proc_var_passing} a
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
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,
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,
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
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
\funcd{fscanf} e \funcd{sscanf}, i cui prototipi sono:
\begin{functions}
\headdecl{stdio.h} \funcdecl{int scanf(const char *format, ...)} Esegue una
\funcd{fscanf} e \funcd{sscanf}, i cui prototipi sono:
\begin{functions}
\headdecl{stdio.h} \funcdecl{int scanf(const char *format, ...)} Esegue una
\bodydesc{Le funzioni ritornano il numero di elementi assegnati. Questi
possono essere in numero inferiore a quelli specificati, ed anche zero.
\bodydesc{Le funzioni ritornano il numero di elementi assegnati. Questi
possono essere in numero inferiore a quelli specificati, ed anche zero.
di errore o fine del file viene invece restituito \val{EOF}.}
\end{functions}
\noindent e come per le analoghe funzioni di scrittura esistono le relative
di errore o fine del file viene invece restituito \val{EOF}.}
\end{functions}
\noindent e come per le analoghe funzioni di scrittura esistono le relative
-puntatori alle variabili che dovranno contenere le conversioni; questo è un
-primo elemento di disagio in quanto è molto facile dimenticarsi di questa
+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
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 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
+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 ecc.), mentre
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 ecc.), mentre
interrotta immediatamente e la funzione ritorna lasciando posizionato lo
stream al primo carattere che non corrisponde.
interrotta immediatamente e la funzione ritorna lasciando posizionato lo
stream al primo carattere che non corrisponde.
relativamente semplice si preferisce usare l'input di linea ed effettuare
scansione e conversione di quanto serve direttamente con una delle funzioni di
relativamente semplice si preferisce usare l'input di linea ed effettuare
scansione e conversione di quanto serve direttamente con una delle funzioni di
- \cmd{flex}, è una implementazione libera di \cmd{lex} un generatore di
- analizzatori lessicali. Per i dettagli si può fare riferimento al manuale
+ \cmd{flex}, è una implementazione libera di \cmd{lex} un generatore di
+ analizzatori lessicali. Per i dettagli si può fare riferimento al manuale
parser \cmd{yacc}, maggiori dettagli possono essere trovati nel relativo
manuale \cite{bison}.} per generare un parser.
parser \cmd{yacc}, maggiori dettagli possono essere trovati nel relativo
manuale \cite{bison}.} per generare un parser.
all'interno di un file per effettuare operazioni di lettura o scrittura in un
punto prestabilito; sempre che l'operazione di riposizionamento sia supportata
all'interno di un file per effettuare operazioni di lettura o scrittura in un
punto prestabilito; sempre che l'operazione di riposizionamento sia supportata
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
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
descriptor, e gli argomenti, a parte il tipo, hanno lo stesso significato; in
descriptor, e gli argomenti, a parte il tipo, hanno lo stesso significato; 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
posizione corrente all'inizio dello stream, ma non esattamente equivalente ad
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
posizione corrente all'inizio dello stream, ma non esattamente equivalente ad
flag di errore e fine del file.
Per ottenere la posizione corrente si usa invece la funzione \funcd{ftell}, il
flag di errore e fine del file.
Per ottenere la posizione corrente si usa invece la funzione \funcd{ftell}, il
\begin{prototype}{stdio.h}{long ftell(FILE *stream)}
Legge la posizione attuale nello stream \param{stream}.
\bodydesc{La funzione restituisce la posizione corrente, o -1 in caso
\begin{prototype}{stdio.h}{long ftell(FILE *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ò
+ 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 \ctyp{long int}}
\end{prototype}
\noindent la funzione restituisce la posizione come numero di byte
essere espressa con un \ctyp{long int}}
\end{prototype}
\noindent la funzione restituisce la posizione come numero di byte
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
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
\funcd{fgetpos} e \funcd{fsetpos}, che invece usano il nuovo tipo
\type{fpos\_t}, ed i cui prototipi sono:
\begin{functions}
\funcd{fgetpos} e \funcd{fsetpos}, che invece usano il nuovo tipo
\type{fpos\_t}, ed i cui prototipi sono:
\begin{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
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
gran parte dei casi un intero a 32 bit, questo diventa un problema quando la
posizione sul file viene espressa con un valore a 64 bit come accade nei
gran parte dei casi un intero a 32 bit, questo diventa un problema quando la
posizione sul file viene espressa con un valore a 64 bit come accade nei
In questa sezione esamineremo alcune funzioni avanzate che permettono di
eseguire operazioni particolari sugli stream, come leggerne gli attributi,
In questa sezione esamineremo alcune funzioni avanzate che permettono di
eseguire operazioni particolari sugli stream, come leggerne gli attributi,
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
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 \funcd{fileno} per ottenere quest'ultimo,
-il prototipo della funzione è:
+attributi dei file. Però, dato che ogni stream si appoggia ad un file
+descriptor, si può usare la funzione \funcd{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}.
\begin{prototype}{stdio.h}{int fileno(FILE *stream)}
Legge il file descriptor sottostante lo stream \param{stream}.
\noindent ed in questo modo diventa possibile usare direttamente \func{fcntl}.
Questo permette di accedere agli attributi del file descriptor sottostante lo
\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
+stream, ma non ci dà nessuna informazione riguardo alle proprietà dello stream
+medesimo. Le \acr{glibc} però supportano alcune estensioni derivate da
-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ò
+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ò
-questo punto necessiterà di informazioni aggiuntive rispetto al semplice
-puntatore allo stream; questo può essere evitato con le due funzioni
+questo punto necessiterà di informazioni aggiuntive rispetto al semplice
+puntatore allo stream; questo può essere evitato con le due funzioni
in quanto permette di trarre conclusioni sullo stato del buffer e del suo
contenuto. Altre due funzioni, \funcd{\_\_freading} e \funcd{\_\_fwriting}
in quanto permette di trarre conclusioni sullo stato del buffer e del suo
contenuto. Altre due funzioni, \funcd{\_\_freading} e \funcd{\_\_fwriting}
- Restituisce un valore diverso da zero se \param{stream} è aperto in sola
- lettura o se l'ultima operazione è stata di lettura.
+ Restituisce un valore diverso da zero se \param{stream} è aperto in sola
+ lettura o se l'ultima operazione è stata di lettura.
- Restituisce un valore diverso da zero se \param{stream} è aperto in sola
- scrittura o se l'ultima operazione è stata di scrittura.
+ Restituisce un valore diverso da zero se \param{stream} è aperto in sola
+ scrittura o se l'ultima operazione è stata di scrittura.
-uno stream è aperto in sola lettura (o sola scrittura) la modalità dell'ultima
-operazione è sempre determinata; l'unica ambiguità è quando non sono state
+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.
ancora eseguite operazioni, in questo caso le funzioni rispondono come se una
operazione ci fosse comunque stata.
Come accennato in sez.~\ref{sec:file_buffering} le librerie definiscono una
serie di funzioni che permettono di controllare il comportamento degli stream;
Come accennato in sez.~\ref{sec:file_buffering} le librerie definiscono una
serie di funzioni che permettono di controllare il comportamento degli stream;
autonomamente sulla base del tipo di file sottostante, ed i buffer vengono
allocati automaticamente.
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 è \funcd{setvbuf}, il
-suo prototipo è:
+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 è \funcd{setvbuf}, il
+suo prototipo è:
\begin{prototype}{stdio.h}{int setvbuf(FILE *stream, char *buf, int mode,
size\_t size)}
\begin{prototype}{stdio.h}{int setvbuf(FILE *stream, char *buf, int mode,
size\_t size)}
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
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} è
+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 \const{BUFSIZ}, che indica le dimensioni generiche del
buffer di uno stream; queste vengono usate dalla funzione \func{setbuf}. Non
definita la macro \const{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).
+è detto però che tale dimensione corrisponda sempre al valore ottimale (che
+può variare a seconda del dispositivo).
di libreria, che sono in grado di farlo in maniera ottimale e trasparente
all'utente (in quanto la deallocazione avviene automaticamente). Inoltre
siccome alcune implementazioni usano parte del buffer per mantenere delle
di libreria, che sono in grado di farlo in maniera ottimale e trasparente
all'utente (in quanto la deallocazione avviene automaticamente). Inoltre
siccome alcune implementazioni usano parte del buffer per mantenere delle
\label{tab:file_stream_buf_mode}
\end{table}
Per evitare che \func{setvbuf} imposti il buffer basta passare un valore
\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à 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
+\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
- bufferizzazione se \param{buf} è \val{NULL}, altrimenti usa \param{buf}
- come buffer di dimensione \const{BUFSIZ} in modalità \textit{fully buffered}.
+ bufferizzazione se \param{buf} è \val{NULL}, altrimenti usa \param{buf}
+ come buffer di dimensione \const{BUFSIZ} in modalità \textit{fully buffered}.
- la bufferizzazione se \param{buf} è \val{NULL}, altrimenti usa \param{buf}
- come buffer di dimensione \param{size} in modalità \textit{fully buffered}.
+ la bufferizzazione se \param{buf} è \val{NULL}, altrimenti usa \param{buf}
+ come buffer di dimensione \param{size} in modalità \textit{fully buffered}.
BSD. Infine le \acr{glibc} provvedono le funzioni non standard\footnote{anche
queste funzioni sono originarie di Solaris.} \funcd{\_\_flbf} e
BSD. Infine le \acr{glibc} provvedono le funzioni non standard\footnote{anche
queste funzioni sono originarie di Solaris.} \funcd{\_\_flbf} e
di uno stream; i cui prototipi sono:
\begin{functions}
\headdecl{stdio\_ext.h}
\funcdecl{int \_\_flbf(FILE *stream)} Restituisce un valore diverso da zero
di uno stream; i cui prototipi sono:
\begin{functions}
\headdecl{stdio\_ext.h}
\funcdecl{int \_\_flbf(FILE *stream)} Restituisce un valore diverso da zero
\funcdecl{size\_t \_\_fbufsize(FILE *stream)} Restituisce le dimensioni del
buffer di \param{stream}.
\end{functions}
\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
-\funcd{fflush}, il suo prototipo è:
+Come già accennato, indipendentemente dalla modalità di bufferizzazione
+scelta, si può forzare lo scarico dei dati sul file con la funzione
+\funcd{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 \val{EOF} in caso di
\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 \val{EOF} in caso di
- errore, impostando \var{errno} a \errval{EBADF} se \param{stream} non è
- aperto o non è aperto in scrittura, o ad uno degli errori di
+ errore, impostando \var{errno} a \errval{EBADF} se \param{stream} non è
+ aperto o non è aperto in scrittura, o ad uno degli errori di
-Se \param{stream} è \val{NULL} lo scarico dei dati è forzato per tutti gli
-stream aperti. Esistono però circostanze, ad esempio quando si vuole essere
+Se \param{stream} è \val{NULL} lo scarico dei dati è forzato per tutti gli
+stream aperti. Esistono però circostanze, ad esempio quando si vuole essere
usare \func{sync} o \func{fsync} (si veda~sez.~\ref{sec:file_sync}).
Infine esistono anche circostanze in cui si vuole scartare tutto l'output
usare \func{sync} o \func{fsync} (si veda~sez.~\ref{sec:file_sync}).
Infine esistono anche circostanze in cui si vuole scartare tutto l'output
\begin{prototype}{stdio.h}{int fpurge(FILE *stream)}
Cancella i buffer di input e di output dello stream \param{stream}.
\begin{prototype}{stdio.h}{int fpurge(FILE *stream)}
Cancella i buffer di input e di output dello stream \param{stream}.
-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),
+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),
Gli stream possono essere usati in applicazioni \textit{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
Gli stream possono essere usati in applicazioni \textit{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
pesantemente dalle richieste necessarie per garantirne l'uso con i
\textit{thread}.
Lo standard POSIX richiede che le operazioni sui file siano atomiche rispetto
ai \textit{thread}, per questo le operazioni sui buffer effettuate dalle
funzioni di libreria durante la lettura e la scrittura di uno stream devono
pesantemente dalle richieste necessarie per garantirne l'uso con i
\textit{thread}.
Lo standard POSIX richiede che le operazioni sui file siano atomiche rispetto
ai \textit{thread}, per questo le operazioni sui buffer effettuate dalle
funzioni di libreria durante la lettura e la scrittura di uno stream devono
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
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
atomicamente, per questo motivo le librerie provvedono anche delle funzioni
\funcd{flockfile}, \funcd{ftrylockfile} e \funcd{funlockfile}, che permettono
la gestione esplicita dei blocchi sugli stream; esse sono disponibili
atomicamente, per questo motivo le librerie provvedono anche delle funzioni
\funcd{flockfile}, \funcd{ftrylockfile} e \funcd{funlockfile}, che permettono
la gestione esplicita dei blocchi sugli stream; esse sono disponibili
Ritorna zero in caso di acquisizione del lock, diverso da zero altrimenti.
\funcdecl{void funlockfile(FILE *stream)} Rilascia il lock dello
Ritorna zero in caso di acquisizione del lock, diverso da zero altrimenti.
\funcdecl{void funlockfile(FILE *stream)} Rilascia il lock dello
\noindent con queste funzioni diventa possibile acquisire un blocco ed
eseguire tutte le operazioni volute, per poi rilasciarlo.
\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 è
+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 è
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
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
+ 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
accade per \func{getc} e \func{putc}) sono realizzate come macro.
La sostituzione di tutte le funzioni di I/O con le relative versioni
lavoro abbastanza noioso; per questo motivo le \acr{glibc} forniscono 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 \funcd{\_\_fsetlocking}, il cui
lavoro abbastanza noioso; per questo motivo le \acr{glibc} forniscono 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 \funcd{\_\_fsetlocking}, il cui
le operazioni di I/O su \param{stream} vengono effettuate rispetto
all'acquisizione implicita del blocco sullo stream.
le operazioni di I/O su \param{stream} vengono effettuate rispetto
all'acquisizione implicita del blocco sullo stream.
% LocalWords: IROTH IWOTH umask fseek fsetpos rewind SEEK CUR EOF EBADF close
% LocalWords: sync fcloseall SOURCE void stdlib of feof ferror clearerr l'I ws
% LocalWords: unlocked fread fwrite size ptr nmemb nelem gcc padding point str
% LocalWords: IROTH IWOTH umask fseek fsetpos rewind SEEK CUR EOF EBADF close
% LocalWords: sync fcloseall SOURCE void stdlib of feof ferror clearerr l'I ws
% LocalWords: unlocked fread fwrite size ptr nmemb nelem gcc padding point str
% LocalWords: getwc fgetwc getwchar wint wchar WEOF putc fputc putchar dell'I
% LocalWords: SVID getw putw parsing peeking ahead ungetc gets fgets string Di
% LocalWords: overflow Aleph stack fputs puts fgetws fputws getline ssize leak
% LocalWords: getwc fgetwc getwchar wint wchar WEOF putc fputc putchar dell'I
% LocalWords: SVID getw putw parsing peeking ahead ungetc gets fgets string Di
% LocalWords: overflow Aleph stack fputs puts fgetws fputws getline ssize leak