X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=filestd.tex;h=db18e5d454230071849b1a7776ca788747c48d57;hp=0a623a06a95597bedffe165a74c99dcfe1bf7ca3;hb=66e83c068629844f84fe4a0d44b382f756c9ef32;hpb=9efe28fd24b23b1fca69f4c5296cb29e4372438c diff --git a/filestd.tex b/filestd.tex index 0a623a0..db18e5d 100644 --- a/filestd.tex +++ b/filestd.tex @@ -1,9 +1,9 @@ %% 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". @@ -21,7 +21,7 @@ dell'interfaccia nell'ultima sezione. \section{Introduzione} \label{sec:file_stream_intro} -Come visto in \capref{cha:file_unix_interface} le operazioni di I/O sui file +Come visto in cap.~\ref{cha:file_unix_interface} le operazioni di I/O sui file sono gestibili a basso livello con l'interfaccia standard unix, che ricorre direttamente alle system call messe a disposizione dal kernel. @@ -67,8 +67,8 @@ A parte i dettagli legati alla gestione delle operazioni di lettura e scrittura (sia per quel che riguarda la bufferizzazione, che le formattazioni), i file stream restano del tutto equivalenti ai file descriptor (sui quali sono basati), ed in particolare continua a valere quanto visto in -\secref{sec:file_sharing} a proposito dell'accesso condiviso ed in -\secref{sec:file_access_control} per il controllo di accesso. +sez.~\ref{sec:file_sharing} a proposito dell'accesso condiviso ed in +sez.~\ref{sec:file_access_control} per il controllo di accesso. \index{file!stream|)} @@ -93,7 +93,7 @@ includendo l'header file \file{stdio.h}. \subsection{Gli stream standard} \label{sec:file_std_stream} -Ai tre file descriptor standard (vedi \secref{sec:file_std_descr}) +Ai tre file descriptor standard (vedi sez.~\ref{sec:file_std_descr}) aperti per ogni processo, corrispondono altrettanti stream, che rappresentano i canali standard di input/output prestabiliti; anche questi tre stream sono identificabili attraverso dei nomi simbolici @@ -200,7 +200,7 @@ comporta l'accesso al kernel\footnote{questo vuol dire che lo stream da cui si legge è in modalità \textit{unbuffered}.} viene anche eseguito lo scarico di tutti i buffer degli stream in scrittura. -In \secref{sec:file_buffering_ctrl} vedremo come la libreria definisca delle +In sez.~\ref{sec:file_buffering_ctrl} vedremo come la libreria definisca delle opportune funzioni per controllare le modalità di bufferizzazione e lo scarico dei dati. @@ -210,7 +210,7 @@ dei dati. \label{sec:file_ansi_base_func} Esamineremo in questa sezione le funzioni base dell'interfaccia degli stream, -analoghe a quelle di \secref{sec:file_base_func} per i file descriptor. In +analoghe a quelle di sez.~\ref{sec:file_base_func} per i file descriptor. In particolare vedremo come aprire, leggere, scrivere e cambiare la posizione corrente in uno stream. @@ -245,11 +245,11 @@ Le funzioni che si possono usare per aprire uno stream sono solo tre: 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 \tabref{tab:file_fopen_mode} (sono possibili varie +valori indicati in tab.~\ref{tab:file_fopen_mode} (sono possibili varie estensioni che vedremo in seguito). L'uso più comune di \func{freopen} è per redirigere uno dei tre file -standard (vedi \secref{sec:file_std_stream}): il file \param{path} viene +standard (vedi sez.~\ref{sec:file_std_stream}): il file \param{path} viene associato a \param{stream} e se questo è uno stream già aperto viene preventivamente chiuso. @@ -294,7 +294,7 @@ possono essere aperti con le funzioni delle librerie standard del C. \end{table} In realtà lo standard ANSI C prevede un totale di 15 possibili valori -diversi per \param{mode}, ma in \tabref{tab:file_fopen_mode} si sono +diversi per \param{mode}, ma in tab.~\ref{tab:file_fopen_mode} si sono riportati solo i sei valori effettivi, ad essi può essere aggiunto pure 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 @@ -304,7 +304,7 @@ compatibilit Le \acr{glibc} supportano alcune estensioni, queste devono essere sempre indicate dopo aver specificato il \param{mode} con uno dei valori di -\tabref{tab:file_fopen_mode}. L'uso del carattere \texttt{x} serve per +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à esiste e si aggiunge questo carattere a \param{mode} la \func{fopen} @@ -319,15 +319,15 @@ opportune funzioni di conversione in lettura e scrittura. Nel caso si usi \func{fdopen} i valori specificati da \param{mode} devono essere compatibili con quelli con cui il file descriptor è stato aperto. Inoltre i modi \cmd{w} e \cmd{w+} non troncano il file. La posizione nello -stream viene impostata a quella corrente nel file descriptor, e le variabili di -errore e di fine del file (vedi \secref{sec:file_io}) sono cancellate. Il file -non viene duplicato e verrà chiuso alla chiusura dello stream. +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 +file non viene duplicato e verrà chiuso alla chiusura dello stream. I nuovi file saranno creati secondo quanto visto in -\secref{sec:file_ownership} ed avranno i permessi di accesso impostati al +sez.~\ref{sec:file_ownership} ed avranno i permessi di accesso impostati al valore \code{S\_IRUSR|S\_IWUSR|S\_IRGRP|S\_IWGRP|S\_IROTH|S\_IWOTH} (pari a \val{0666}) modificato secondo il valore di \acr{umask} per il processo (si -veda \secref{sec:file_umask}). +veda sez.~\ref{sec:file_umask}). In caso di file aperti in lettura e scrittura occorre ricordarsi che c'è di mezzo una bufferizzazione; per questo motivo lo standard ANSI C @@ -345,7 +345,7 @@ un'operazione nominalmente nulla come \code{fseek(file, 0, SEEK\_CUR)} sufficiente a garantire la sincronizzazione. Una volta aperto lo stream, si può cambiare la modalità di bufferizzazione -(si veda \secref{sec:file_buffering_ctrl}) fintanto che non si è effettuato +(si veda sez.~\ref{sec:file_buffering_ctrl}) fintanto che non si è effettuato alcuna operazione di I/O sul file. Uno stream viene chiuso con la funzione \funcd{fclose} il cui prototipo è: @@ -364,7 +364,7 @@ e scarta tutti i dati in ingresso; se era stato allocato un buffer per lo stream questo verrà rilasciato. La funzione effettua lo scarico solo per i dati presenti nei buffer in user space usati dalle \acr{glibc}; se si vuole essere sicuri che il kernel forzi la scrittura su disco occorrerà effettuare -una \func{sync} (vedi \secref{sec:file_sync}). +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 @@ -379,7 +379,7 @@ 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 \secref{sec:proc_exit}). +visto in sez.~\ref{sec:proc_exit}). \subsection{Lettura e scrittura su uno stream} @@ -391,12 +391,12 @@ 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 \secref{sec:file_binary_io}. + volta, vedi sez.~\ref{sec:file_binary_io}. \item\textsl{a caratteri} in cui si legge/scrive un carattere alla volta (con la bufferizzazione gestita automaticamente dalla libreria), - vedi \secref{sec:file_char_io}. + vedi sez.~\ref{sec:file_char_io}. \item\textsl{di linea} in cui si legge/scrive una linea alla volta (terminata - dal carattere di newline \verb|'\n'|), vedi \secref{sec:file_line_io}. + dal carattere di newline \verb|'\n'|), vedi sez.~\ref{sec:file_line_io}. \end{enumerate*} ed inoltre la modalità di input/output formattato. @@ -417,7 +417,7 @@ Siccome la condizione di end-of-file 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 -una altra occasione, (si veda \secref{sec:sys_errno} per i dettagli del +una altra occasione, (si veda sez.~\ref{sec:sys_errno} per i dettagli del funzionamento di \var{errno}). Per questo motivo tutte le implementazioni delle librerie standard @@ -451,7 +451,7 @@ la funzione \funcd{clearerr}, il cui prototipo corretta la causa di un errore per evitare di mantenere i flag attivi, così da poter rilevare una successiva ulteriore condizione di errore. Di questa funzione esiste una analoga \func{clearerr\_unlocked} che non esegue il blocco -dello stream (vedi \secref{sec:file_stream_thread}). +dello stream (vedi sez.~\ref{sec:file_stream_thread}). \subsection{Input/output binario} @@ -535,7 +535,7 @@ eventuali differenze. Le \acr{glibc} definiscono altre due funzioni per l'I/O binario, \funcd{fread\_unlocked} e \funcd{fwrite\_unlocked} che evitano il lock implicito dello stream, usato per dalla librerie per la gestione delle -applicazioni multi-thread (si veda \secref{sec:file_stream_thread} per i +applicazioni multi-thread (si veda sez.~\ref{sec:file_stream_thread} per i dettagli), i loro prototipi sono: \begin{functions} \headdecl{stdio.h} @@ -582,7 +582,7 @@ differenza viene implementata con una macro, per cui occorre stare attenti a cosa le si passa come argomento, infatti \param{stream} può essere valutato più volte nell'esecuzione, e non viene passato in copia con il -meccanismo visto in \secref{sec:proc_var_passing}; per questo motivo se +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 @@ -708,7 +708,7 @@ successivamente. Infine si tenga presente che \func{ungetc} non altera il contenuto del file, ma opera esclusivamente sul buffer interno. Se si esegue una qualunque delle operazioni di riposizionamento (vedi -\secref{sec:file_fseek}) i caratteri rimandati indietro vengono +sez.~\ref{sec:file_fseek}) i caratteri rimandati indietro vengono scartati. @@ -747,9 +747,10 @@ viene restituito un \val{NULL}, ed il buffer \param{buf} non viene toccato. L'uso di \func{gets} è deprecato e deve essere assolutamente evitato; la funzione infatti non controlla il numero di byte letti, per cui nel caso la stringa letta superi le dimensioni del buffer, si avrà un \textit{buffer - overflow}\index{buffer overflow}, con sovrascrittura della memoria del -processo adiacente al buffer.\footnote{questa tecnica è spiegata in dettaglio - e con molta efficacia nell'ormai famoso articolo di Aleph1 \cite{StS}.} + overflow}\index{\textit{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 @@ -821,7 +822,7 @@ 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 esattamente le stesse operazioni delle loro equivalenti, evitando però il lock -implicito dello stream (vedi \secref{sec:file_stream_thread}). Come per le +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}. @@ -862,22 +863,22 @@ linea. Quest'ultimo \emph{deve} essere stato allocato in precedenza con una locale); come secondo parametro la funzione vuole l'indirizzo della variabile contenente le dimensioni del buffer suddetto. -Se il buffer di destinazione è sufficientemente ampio la stringa viene -scritta subito, altrimenti il buffer viene allargato usando -\func{realloc} e la nuova dimensione ed il nuovo puntatore vengono -passata indietro (si noti infatti come per entrambi i parametri si siano -usati dei \textit{value result argument}, passando dei puntatori anziché -i valori delle variabili, secondo la tecnica spiegata in -\secref{sec:proc_var_passing}). +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 +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 memory leak\index{\textit{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 @@ -926,13 +927,14 @@ L'output formattato viene eseguito con una delle 13 funzioni della famiglia \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 -si consiglia l'uso dell'alternativa \funcd{snprintf}, il cui prototipo è: +possibili \textit{buffer overflow}\index{\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, ...)} Identica a \func{sprintf}, ma non scrive su \param{str} più di @@ -994,7 +996,7 @@ La stringa vengono passati invariati all'output, e da direttive di conversione, in cui devono essere sempre presenti il carattere \texttt{\%}, che introduce la direttiva, ed uno degli specificatori di conversione (riportati in -\tabref{tab:file_format_spec}) che la conclude. +tab.~\ref{tab:file_format_spec}) che la conclude. \begin{table}[htb] \centering @@ -1031,13 +1033,13 @@ questo ordine: \begin{itemize*} \item uno specificatore del parametro da usare (terminato da un \val{\$}), \item uno o più flag (i cui valori possibili sono riassunti in - \tabref{tab:file_format_flag}) che controllano il formato di stampa della + tab.~\ref{tab:file_format_flag}) che controllano il formato di stampa della conversione, \item uno specificatore di larghezza (un numero decimale), eventualmente seguito (per i numeri in virgola mobile) da un specificatore di precisione (un altro numero decimale), \item uno specificatore del tipo di dato, che ne indica la dimensione (i cui - valori possibili sono riassunti in \tabref{tab:file_format_type}). + valori possibili sono riassunti in tab.~\ref{tab:file_format_type}). \end{itemize*} @@ -1081,7 +1083,7 @@ manuale di \func{printf} e nella documentazione delle \acr{glibc}. Una versione alternativa delle funzioni di output formattato, che permettono di usare il puntatore ad una lista di argomenti (vedi -\secref{sec:proc_variadic}), sono \funcd{vprintf}, \funcd{vfprintf} e +sez.~\ref{sec:proc_variadic}), sono \funcd{vprintf}, \funcd{vfprintf} e \funcd{vsprintf}, i cui prototipi sono: \begin{functions} \headdecl{stdio.h} @@ -1104,7 +1106,7 @@ di usare il puntatore ad una lista di argomenti (vedi si vogliono passare ad una routine di stampa, passando direttamente la lista tramite il parametro \param{ap}. Per poter far questo ovviamente la lista dei parametri dovrà essere opportunamente trattata (l'argomento è esaminato in -\secref{sec:proc_variadic}), e dopo l'esecuzione della funzione l'argomento +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). @@ -1116,7 +1118,8 @@ scritti sulla stringa di destinazione: 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\index{\textit{buffer~overflow}}. Per eliminare alla radice questi problemi, le \acr{glibc} supportano una @@ -1140,11 +1143,12 @@ sono: \end{functions} Entrambe le funzioni prendono come parametro \param{strptr} che deve essere l'indirizzo di un puntatore ad una stringa di caratteri, in cui verrà -restituito (si ricordi quanto detto in \secref{sec:proc_var_passing} a -proposito dei \textit{value result argument}) l'indirizzo della stringa -allocata automaticamente dalle funzioni. Occorre inoltre ricordarsi di -invocare \func{free} per liberare detto puntatore quando la stringa non serve -più, onde evitare memory leak\index{memory leak}. +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{\textit{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 @@ -1227,7 +1231,7 @@ punto prestabilito; sempre che l'operazione di riposizionamento sia supportata dal file sottostante lo stream, quando cioè si ha a che fare con quello che viene detto un file ad \textsl{accesso casuale}.\footnote{dato che in un sistema Unix esistono vari tipi di file, come le fifo ed i 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 è @@ -1257,7 +1261,7 @@ stream sono \funcd{fseek} e \funcd{rewind} i cui prototipi sono: L'uso di \func{fseek} è del tutto analogo a quello di \func{lseek} per i file descriptor, ed i parametri, a parte il tipo, hanno lo stesso significato; in particolare \param{whence} assume gli stessi valori già visti in -\secref{sec:file_lseek}. La funzione restituisce 0 in caso di successo e -1 +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 una \code{fseek(stream, 0L, SEEK\_SET)} in quanto vengono cancellati anche i @@ -1376,7 +1380,7 @@ operazione ci fosse comunque stata. \subsection{Il controllo della bufferizzazione} \label{sec:file_buffering_ctrl} -Come accennato in \secref{sec:file_buffering} le librerie definiscono una +Come accennato in sez.~\ref{sec:file_buffering} le librerie definiscono una serie di funzioni che permettono di controllare il comportamento degli stream; se non si è specificato nulla, la modalità di buffering viene decisa autonomamente sulla base del tipo di file sottostante, ed i buffer vengono @@ -1443,7 +1447,7 @@ 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} usando il buffer allocato automaticamente dal sistema. Si potrà comunque modificare la modalità di bufferizzazione, passando in \param{mode} uno degli -opportuni valori elencati in \tabref{tab:file_stream_buf_mode}. Qualora si +opportuni valori elencati in tab.~\ref{tab:file_stream_buf_mode}. Qualora si specifichi la modalità non bufferizzata i valori di \param{buf} e \param{size} vengono sempre ignorati. @@ -1511,7 +1515,7 @@ funzione \funcd{\_flushlbf}, il cui prototipo Si ricordi comunque che lo scarico dei dati dai buffer effettuato da queste funzioni non comporta la scrittura di questi su disco; se si vuole che il kernel dia effettivamente avvio alle operazioni di scrittura su disco occorre -usare \func{sync} o \func{fsync} (si veda~\secref{sec:file_sync}). +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 pendente; per questo si può usare \funcd{fpurge}, il cui prototipo è: