%% fileio.tex (merge fileunix.tex - filestd.tex)
%%
%% Copyright (C) 2000-2014 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 "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".
%%

\chapter{La gestione dell'I/O su file}
\label{cha:file_IO_interface}

Esamineremo in questo capitolo le due interfacce di programmazione che
consentono di gestire i dati mantenuti nei file. Cominceremo con quella nativa
del sistema, detta dei \itindex{file~descriptor} \textit{file descriptor}, che
viene fornita direttamente dalle \textit{system call} e che non prevede
funzionalità evolute come la bufferizzazione o funzioni di lettura o scrittura
formattata. Esamineremo poi anche l'interfaccia definita dallo standard ANSI
C, che viene chiamata dei \textit{file stream} o anche più brevemente degli
\textit{stream}. Per entrambe dopo una introduzione alle caratteristiche
generali tratteremo le funzioni base per la gestione dell'I/O, lasciando per
ultime le caratteristiche più avanzate.


\section{L'interfaccia dei \textit{file descriptor}}
\label{sec:file_unix_interface}


Come visto in sez.~\ref{sec:file_vfs_work} il kernel mette a disposizione
tramite il \itindex{Virtual~File~System} \textit{Virtual File System} una
serie di \textit{system call} che consentono di operare sui file in maniera
generale. Abbiamo trattato quelle relative alla gestione delle proprietà dei
file nel precedente capitolo, vedremo quelle che si applicano al contenuto dei
file in questa sezione, iniziando con una breve introduzione sull'architettura
dei \textit{file descriptor} per poi trattare le funzioni di base e le
modalità con cui consentono di gestire i dati memorizzati sui file.


\subsection{I \textit{file descriptor}}
\label{sec:file_fd}

\itindbeg{file~descriptor} 

L'accesso al contenuto dei file viene effettuato, sia pure con differenze
nella realizzazione pratica, in maniera sostanzialmente identica in tutte le
implementazioni di un sistema unix-like, ricorrendo a quella che viene
chiamata l'interfaccia dei \textit{file descriptor}.

Per poter accedere al contenuto di un file occorre creare un canale di
comunicazione con il kernel che renda possibile operare su di esso. Questo si
fa aprendo il file con la funzione \func{open} (vedi
sez.~\ref{sec:file_open_close}) che provvederà a localizzare \itindex{inode}
l'\textit{inode} del file e inizializzare i puntatori che rendono disponibili
le funzioni che il \itindex{Virtual~File~System} VFS mette a disposizione
(quelle di tab.~\ref{tab:file_file_operations}). Una volta terminate le
operazioni, il file dovrà essere chiuso, e questo chiuderà il canale di
comunicazione impedendo ogni ulteriore operazione.

All'interno di ogni processo i file aperti sono identificati da un numero
intero non negativo, che viene chiamato \textit{file descriptor}.  Quando un
file viene aperto la funzione \func{open} restituisce questo numero, tutte le
ulteriori operazioni dovranno essere compiute specificando questo stesso
numero come argomento alle varie funzioni dell'interfaccia.

Per capire come funziona il meccanismo occorre spiegare a grandi linee come il
kernel gestisce l'interazione fra processi e file.  Abbiamo già accennato in
sez.~\ref{sec:proc_hierarchy} come il kernel mantenga un elenco di tutti
processi nella cosiddetta \itindex{process~table} \textit{process table}. Lo
stesso, come accennato in sez.~\ref{sec:file_vfs_work}, vale anche per tutti i
file aperti, il cui elenco viene mantenuto nella cosiddetta
\itindex{file~table} \textit{file table}.

La \itindex{process~table} \textit{process table} è una tabella che contiene
una voce per ciascun processo attivo nel sistema. Ciascuna voce è costituita
dal puntatore a una struttura di tipo \kstruct{task\_struct} nella quale sono
raccolte tutte le informazioni relative al processo, fra queste informazioni
c'è anche il puntatore ad una ulteriore struttura di tipo
\kstruct{files\_struct},\footnote{la definizione corrente di questa struttura
  si trova nel file \texttt{include/linux/fdtable.h} dei sorgenti del kernel,
  quella mostrata in fig.~\ref{fig:file_proc_file} è una versione pesantemente
  semplificata.} che contiene le informazioni relative ai file che il processo
ha aperto.

La \itindex{file~table} \textit{file table} è una tabella che contiene una
voce per ciascun file che è stato aperto nel sistema. Come accennato in
sez.~\ref{sec:file_vfs_work} per ogni file aperto viene allocata una struttura
\kstruct{file} e la \textit{file table} è costituita da un elenco di puntatori
a ciascuna di queste strutture, che, come illustrato in
fig.~\ref{fig:kstruct_file}, contengono le informazioni necessarie per la
gestione dei file, ed in particolare:
\begin{itemize*}
\item i flag di stato \itindex{file~status~flag} del file nel campo
  \var{f\_flags}.
\item la posizione corrente nel file, il cosiddetto \textit{offset}, nel campo
  \var{f\_pos}.
\item un puntatore alla struttura \kstruct{inode} che identifica
  \itindex{inode} l'\textit{inode} del file.\footnote{nel kernel 2.4.x si è in
    realtà passati ad un puntatore ad una struttura \kstruct{dentry} che punta
    a sua volta \itindex{inode} all'\textit{inode} passando per la nuova
    struttura del VFS.}
\item un puntatore \var{f\_op} alla tabella delle funzioni che si possono
  usare sul file.\footnote{quelle della struttura \kstruct{file\_operation},
    descritte sommariamente in tab.~\ref{tab:file_file_operations}.}
\end{itemize*}

\begin{figure}[!htb]
  \centering
  \includegraphics[width=12cm]{img/procfile}
  \caption{Schema della architettura dell'accesso ai file attraverso
  l'interfaccia dei \textit{file descriptor}.}
  \label{fig:file_proc_file}
\end{figure}

In fig.~\ref{fig:file_proc_file} si è riportato uno schema semplificato in cui
è illustrata questa architettura, ed in cui si sono evidenziate le
interrelazioni fra la \itindex{file~table} \textit{file table}, la
\itindex{process~table} \textit{process table} e le varie strutture di dati
che il kernel mantiene per ciascun file e ciascun processo.

Come si può notare alla fine il collegamento che consente di porre in
relazione i file ed i processi è effettuato attraverso i dati mantenuti nella
struttura \kstruct{files\_struct}, essa infatti contiene alcune informazioni
essenziali come:
\begin{itemize*}
\item i flag relativi ai file aperti dal processo.
\item il numero di file aperti dal processo.
\item la \itindex{file~descriptor~table} \textit{file descriptor table}, una
  tabella con i puntatori, per ciascun file aperto, alla relativa voce nella
  \itindex{file~table} \textit{file table}.
\end{itemize*}

In questa infrastruttura un \textit{file descriptor} non è altro che l'intero
positivo che indicizza quest'ultima tabella, e che consente di recuperare il
puntatore alla struttura \kstruct{file} corrispondente al file aperto dal
processo a cui era stato assegnato questo indice. Una volta ottenuta grazie
al \textit{file descriptor} la struttura \kstruct{file} corrispondente al file
voluto nella \itindex{file~table} \textit{file table}, il kernel potrà usare
le funzioni messe disposizione dal VFS per eseguire sul file tutte le
operazioni necessarie.

Il meccanismo dell'apertura dei file prevede che venga sempre fornito il primo
\textit{file descriptor} libero nella tabella, e per questo motivo essi
vengono assegnati in successione tutte le volte che si apre un nuovo file,
posto che non ne sia stato chiuso nessuno in precedenza.

In tutti i sistemi unix-like esiste una convenzione generale per cui ogni
processo si aspetta di avere sempre tre file aperti che, per quanto appena
detto, avranno come \itindex{file~descriptor} \textit{file descriptor} i
valori 0, 1 e 2.  Il primo file è sempre associato al cosiddetto
\itindex{standard~input} \textit{standard input}, è cioè il file da cui un
processo si aspetta di dover leggere i dati in ingresso. Il secondo file è il
cosiddetto \itindex{standard~output} \textit{standard output}, cioè quello su
cui ci si aspetta di dover scrivere i dati in uscita. Il terzo è lo
\itindex{standard~error} \textit{standard error}, su cui vengono scritti i
dati relativi agli errori.

Benché questa sia soltanto una convenzione, essa è seguita dalla gran parte
delle applicazioni, e non aderirvi potrebbe portare a problemi di
interoperabilità.  Nel caso della shell tutti questi file sono associati al
terminale di controllo, e corrispondono quindi alla lettura della tastiera per
l'ingresso e alla scrittura sul terminale per l'uscita.  Lo standard POSIX.1
provvede, al posto dei valori numerici, tre costanti simboliche, definite in
tab.~\ref{tab:file_std_files}.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|l|}
    \hline
    \textbf{File} & \textbf{Significato} \\
    \hline
    \hline
    \const{STDIN\_FILENO}  & \textit{file descriptor} dello
                             \itindex{standard~input} \textit{standard
                               input}.\\ 
    \const{STDOUT\_FILENO} & \textit{file descriptor} dello
                             \itindex{standard~output} \textit{standard
                               output}.\\
    \const{STDERR\_FILENO} & \textit{file descriptor} dello \textit{standard
                               error}.\\
    \hline
  \end{tabular}
  \caption{Costanti definite in \headfile{unistd.h} per i file standard.}
  \label{tab:file_std_files}
\end{table}

In fig.~\ref{fig:file_proc_file} si è rappresentata una situazione diversa
rispetto a quella usuale della shell, in cui tutti e tre questi file fanno
riferimento al terminale su cui si opera. Nell'esempio invece viene illustrata
la situazione di un programma in cui lo \itindex{standard~input}
\textit{standard input} è associato ad un file mentre lo
\itindex{standard~output} \textit{standard output} e lo
\itindex{standard~error} \textit{standard error} sono associati ad un altro
file.  Si noti poi come per questi ultimi le strutture \kstruct{file} nella
\itindex{file~table} \textit{file table}, pur essendo distinte, fanno
riferimento allo stesso \itindex{inode} \textit{inode}, dato che il file che è
stato aperto lo stesso. Questo è quello che avviene normalmente quando si apre
più volte lo stesso file.

Si ritrova quindi anche con le voci della \itindex{file~table} \textit{file
  table} una situazione analoga di quella delle voci di una directory, con la
possibilità di avere più voci che fanno riferimento allo stesso
\itindex{inode} \textit{inode}. L'analogia è in realtà molto stretta perché
quando si cancella un file, il kernel verifica anche che non resti nessun
riferimento in una una qualunque voce della \itindex{file~table} \textit{file
  table} prima di liberare le risorse ad esso associate e disallocare il
relativo \itindex{inode} \textit{inode}.

Nelle vecchie versioni di Unix (ed anche in Linux fino al kernel 2.0.x) il
numero di file aperti era anche soggetto ad un limite massimo dato dalle
dimensioni del vettore di puntatori con cui era realizzata la tabella dei file
descriptor dentro \kstruct{files\_struct}. Questo limite intrinseco nei kernel
più recenti non sussiste più, dato che si è passati da un vettore ad una
lista, ma restano i limiti imposti dall'amministratore (vedi
sez.~\ref{sec:sys_limits}).



\subsection{Apertura, creazione e chiusura di un file}
\label{sec:file_open_close}

La funzione di sistema \funcd{open} è la principale funzione dell'interfaccia
di gestione dei file, quella che dato un \textit{pathname} consente di
ottenere un file descriptor ``\textsl{aprendo}'' il file
corrispondente,\footnote{è \func{open} che alloca \kstruct{file}, la inserisce
  nella \itindex{file~table} \textit{file table} e crea il riferimento nella
  \kstruct{files\_struct} del processo.} il suo prototipo è:

\begin{funcproto}{
\fhead{sys/types.h}
\fhead{sys/stat.h}
\fhead{fcntl.h}
\fdecl{int open(const char *pathname, int flags)}
\fdecl{int open(const char *pathname, int flags, mode\_t mode)}

\fdesc{Apre un file.} 
}

{La funzione ritorna il file descriptor in caso di successo e $-1$ per un
  errore, nel qual caso \var{errno} assumerà uno dei valori:
  \begin{errlist}
  \item[\errcode{EEXIST}] \param{pathname} esiste e si è specificato
    \const{O\_CREAT} e \const{O\_EXCL}.
  \item[\errcode{EINTR}] la funzione era bloccata ed è stata interrotta da un
    segnale (vedi sez.~\ref{sec:sig_gen_beha}).
  \item[\errcode{EISDIR}] \param{pathname} indica una directory e si è tentato
    l'accesso in scrittura o in lettura/scrittura.
  \item[\errcode{EFBIG}] il file è troppo grande per essere aperto (lo
    standard richiederebbe \errval{EOVERFLOW}).
  \item[\errcode{ELOOP}] si sono incontrati troppi collegamenti simbolici nel
    risolvere \param{pathname} o si è indicato \const{O\_NOFOLLOW} e
    \param{pathname} è un collegamento simbolico.
  \item[\errcode{ENODEV}] \param{pathname} si riferisce a un file di
    dispositivo che non esiste.
  \item[\errcode{ENOENT}] \param{pathname} non esiste e non si è richiesto
    \const{O\_CREAT}, o non esiste un suo componente. 
  \item[\errcode{ENOTDIR}] si è specificato \const{O\_DIRECTORY} e
    \param{pathname} non è una directory.
  \item[\errcode{ENXIO}] si sono impostati \const{O\_NONBLOCK} o
    \const{O\_WRONLY} ed il file è una fifo che non viene letta da nessun
    processo o \param{pathname} è un file di dispositivo ma il dispositivo è
    assente.
  \item[\errcode{EPERM}] si è specificato \const{O\_NOATIME} e non si è né
    amministratori né proprietari del file.
  \item[\errcode{ETXTBSY}] si è cercato di accedere in scrittura all'immagine
    di un programma in esecuzione.
  \item[\errcode{EWOULDBLOCK}] la funzione si sarebbe bloccata ma si è
    richiesto \const{O\_NONBLOCK}.
  \end{errlist}
  ed inoltre \errval{EACCES}, \errval{EFAULT}, \errval{EMFILE},
  \errval{ENAMETOOLONG}, \errval{ENFILE}, \errval{ENOMEM}, \errval{ENOSPC},
  \errval{EROFS}, nel loro significato generico.}
\end{funcproto}

La funzione apre il file indicato da \param{pathname} nella modalità indicata
da \param{flags}. Essa può essere invocata in due modi diversi, specificando
opzionalmente un terzo argomento \param{mode}. Qualora il file non esista e
venga creato, questo argomento consente di indicare quali permessi dovranno
essergli assegnati. I valori possibili sono gli stessi già visti in
sez.~\ref{sec:file_perm_overview} e possono essere specificati come OR binario
delle costanti descritte in tab.~\ref{tab:file_bit_perm}. Questi permessi sono
comunque filtrati dal valore della \itindex{umask} \textit{umask} (vedi
sez.~\ref{sec:file_perm_management}) del processo.

La funzione restituisce sempre il primo file descriptor libero, una
caratteristica che permette di prevedere qual è il valore del file descriptor
che si otterrà al ritorno di \func{open}, e che viene spesso usata dalle
applicazioni per sostituire i file corrispondenti ai file standard visti in
tab.~\ref{tab:file_std_files}. Se ad esempio si chiude lo
\itindex{standard~input} \textit{standard input} e si apre subito dopo un
nuovo file questo diventerà il nuovo \itindex{standard~input} \textit{standard
  input} dato che avrà il file descriptor 0.

Al momento dell'apertura il nuovo file descriptor non è condiviso con nessun
altro processo (torneremo sul significato della condivisione dei file
descriptor, che in genere si ottiene dopo una \func{fork}, in
sez.~\ref{sec:file_shared_access}) ed è impostato, come accennato in
sez.~\ref{sec:proc_exec}, per restare aperto attraverso una
\func{exec}. Inoltre la posizione sul file, il cosiddetto \textit{offset}, è
impostata all'inizio del file. Una volta aperto un file si potrà operare su di
esso direttamente tramite il file descriptor, e quanto avviene al
\textit{pathname} con cui lo si è aperto sarà del tutto ininfluente.

Il comportamento della funzione, e le diverse modalità con cui può essere
aperto il file, vengono controllati dall'argomento \param{flags} il cui valore
deve essere indicato come maschera binaria in cui ciascun bit ha un
significato specifico.  Alcuni di questi bit vanno anche a costituire i
cosiddetti \textsl{flag di stato} del file (i cosiddetti
\itindex{file~status~flag} \textit{file status flags}), che vengono mantenuti
nel campo \var{f\_flags} della struttura \kstruct{file} che abbiamo riportato
anche in fig.~\ref{fig:file_proc_file}).

Ciascun flag viene identificato da una apposita costante, ed il valore
di \param{flags} deve essere specificato come OR aritmetico di queste
costanti. Inoltre per evitare problemi di compatibilità con funzionalità che
non sono previste o non ancora supportate in versioni meno recenti del kernel,
la \func{open} di Linux ignora i flag che non riconosce, pertanto
l'indicazione di un flag inesistente non provoca una condizione di errore.

I vari bit che si possono usare come componenti di \param{flags} sono divisi
in tre gruppi principali. Il primo gruppo è quello dei cosiddetti flag delle
\textsl{modalità di accesso} (o \textit{access mode flags}), che specificano
che tipo di accesso si effettuerà sul file, fra lettura, scrittura e
lettura/scrittura. Questa modalità deve essere indicata usando una delle
costanti di tab.~\ref{tab:open_access_mode_flag}.

\begin{table}[htb]
  \centering
  \footnotesize
    \begin{tabular}[c]{|l|l|}
      \hline
      \textbf{Flag} & \textbf{Significato} \\
      \hline
      \hline
      \const{O\_RDONLY} & Apre il file in sola lettura.\\
      \const{O\_WRONLY} & Apre il file in sola scrittura.\\
      \const{O\_RDWR}   & Apre il file sia in lettura che in scrittura.\\
      \hline
    \end{tabular}
    \caption{Le tre costanti che identificano le modalità di accesso
      nell'apertura di un file.}
  \label{tab:open_access_mode_flag}
\end{table}

A differenza di tutti gli altri flag che vedremo in seguito, in questo caso
non si ha a che fare con singoli bit separati dell'argomento \param{flags}, ma
con un numero composto da due bit. Questo significa ad esempio che la
combinazione \code{\const{O\_RDONLY}|\const{O\_WRONLY}} non è affatto
equivalente a \const{O\_RDWR}, e non deve essere usata.\footnote{in realtà
  su Linux, dove i valori per le tre costanti di
  tab.~\ref{tab:open_access_mode_flag} sono rispettivamente $0$, $1$ e $2$, il
  valore $3$ viene usato con un significato speciale, ed assolutamente fuori
  standard, disponibile solo per i file di dispositivo e solo per alcuni
  driver, in cui si richiede la verifica della capacità di accesso in lettura
  e scrittura ma viene restituito un file descriptor che non può essere letto
  o scritto, ma solo usato con una \func{ioctl} (vedi
  sez.~\ref{sec:file_fcntl_ioctl}).}

La modalità di accesso deve sempre essere specificata quando si apre un file,
il valore indicato in \param{flags} viene salvato nei
\itindex{file~status~flag} \textit{file status flags}, e può essere riletto
con \func{fcntl} (vedi sez.~\ref{sec:file_fcntl_ioctl}), il relativo valore
può essere poi ottenuto un AND aritmetico della maschera binaria
\const{O\_ACCMODE}, ma non può essere modificato. Nella \acr{glibc} sono
definite inoltre \const{O\_READ} come sinonimo di \const{O\_RDONLY} e
\const{O\_WRITE} come sinonimo di \const{O\_WRONLY}.\footnote{si tratta di
  definizioni completamente fuori standard, attinenti, insieme a
  \const{O\_EXEC} che permetterebbe l'apertura di un file per l'esecuzione, ad
  un non meglio precisato ``\textit{GNU system}''; pur essendo equivalenti
  alle definizioni classiche non è comunque il caso di utilizzarle.}

Il secondo gruppo di flag è quello delle \textsl{modalità di
  apertura},\footnote{la pagina di manuale di \func{open} parla di
  \textit{file creation flags}, ma alcuni di questi flag non hanno nulla a che
  fare con la creazione dei file, mentre il manuale dalla \acr{glibc} parla di
  più correttamente di \textit{open-time flags}, dato che si tratta di flag il
  cui significato ha senso solo al momento dell'apertura del file.} che
permettono di specificare alcune delle caratteristiche del comportamento di
\func{open} nel momento in viene eseguita per aprire un file. Questi flag
hanno effetto solo nella chiamata della funzione, non sono memorizzati fra i
\itindex{file~status~flag} \textit{file status flags} e non possono essere
riletti da \func{fcntl} (vedi sez.~\ref{sec:file_fcntl_ioctl}).

\begin{table}[htb]
  \centering
  \footnotesize
    \begin{tabular}[c]{|l|p{10 cm}|}
      \hline
      \textbf{Flag} & \textbf{Significato} \\
      \hline
      \hline
      \const{O\_CREAT} &    Se il file non esiste verrà creato, con le regole
                            di titolarità del file viste in
                            sez.~\ref{sec:file_ownership_management}. Se si
                            imposta questo flag l'argomento \param{mode} deve
                            essere sempre specificato.\\  
      \const{O\_DIRECTORY}& Se \param{pathname} non è una directory la
                            chiamata fallisce. Questo flag, introdotto con il
                            kernel 2.1.126, è specifico di Linux e
                            serve ad evitare dei possibili
                            \itindex{Denial~of~Service~(DoS)}
                            \textit{DoS}\footnotemark quando \func{opendir} 
                            viene chiamata su una fifo o su un dispositivo
                            associato ad una unità a nastri. Non viene
                            usato al di fuori dell'implementazione di
                            \func{opendir}, ed è utilizzabile soltanto se si è
                            definita la macro \macro{\_GNU\_SOURCE}.\\
      \const{O\_EXCL}     & Deve essere usato in congiunzione con
                            \const{O\_CREAT} ed in tal caso impone che il file
                            indicato da \param{pathname} non sia già esistente
                            (altrimenti causa il fallimento della chiamata con
                            un errore di \errcode{EEXIST}).\\
      \const{O\_LARGEFILE}& Viene usato sui sistemi a 32 bit per richiedere
                            l'apertura di file molto grandi, la cui
                            dimensione non è rappresentabile con la versione a
                            32 bit del tipo \type{off\_t}, utilizzando
                            l'interfaccia alternativa abilitata con la
                            macro \macro{\_LARGEFILE64\_SOURCE}. Come
                            illustrato in sez.~\ref{sec:intro_gcc_glibc_std} è
                            sempre preferibile usare la conversione automatica
                            delle funzioni che si attiva assegnando a $64$ la
                            macro \macro{\_FILE\_OFFSET\_BITS}, e non usare mai
                            questo flag.\\
      \const{O\_NOCTTY}   & Se \param{pathname} si riferisce ad un dispositivo
                            di terminale, questo non diventerà il terminale di
                            controllo, anche se il processo non ne ha ancora
                            uno (si veda sez.~\ref{sec:sess_ctrl_term}).\\ 
      \const{O\_NOFOLLOW} & Se \param{pathname} è un collegamento simbolico
                            la chiamata fallisce. Questa è un'estensione BSD
                            aggiunta in Linux a partire dal kernel
                            2.1.126, ed utilizzabile soltanto se si è definita
                            la macro \macro{\_GNU\_SOURCE}.\\ 
      \const{O\_TRUNC}    & Se usato su un file di dati aperto in scrittura,
                            ne tronca la lunghezza a zero; con un terminale o
                            una fifo viene ignorato, negli altri casi il
                            comportamento non è specificato.\\ 
      \hline
    \end{tabular}
    \caption{Le costanti che identificano le \textit{modalità di apertura} di
      un file.} 
  \label{tab:open_time_flag}
\end{table}


% TODO: aggiungere O_TMPFILE per la creazione di file temporanei senza che
% questi appaiano sul filesystem, introdotto con il 3.11, vedi:
% https://lwn.net/Articles/556512/, http://kernelnewbies.org/Linux_3.11
% https://lwn.net/Articles/558598/

\footnotetext{acronimo di \itindex{Denial~of~Service~(DoS)} \textit{Denial of
    Service}, si chiamano così attacchi miranti ad impedire un servizio
  causando una qualche forma di carico eccessivo per il sistema, che resta
  bloccato nelle risposte all'attacco.}

Si è riportato in tab.~\ref{tab:open_time_flag} l'elenco dei flag delle
\textsl{modalità di apertura}.\footnote{la \acr{glibc} definisce anche i due
  flag \const{O\_SHLOCK}, che aprirebbe il file con uno \textit{shared lock} e
  \const{O\_EXLOCK} che lo aprirebbe con un \textit{exclusive lock} (vedi
  sez.~\ref{sec:file_locking}, si tratta di opzioni specifiche di BSD, che non
  esistono con Linux.}  Uno di questi, \const{O\_EXCL}, ha senso solo se usato
in combinazione a \const{O\_CREAT} quando si vuole creare un nuovo file per
assicurarsi che questo non esista di già, e lo si usa spesso per creare i
cosiddetti \index{file!di lock} ``\textsl{file di lock}'' (vedi
sez.~\ref{sec:ipc_file_lock}). Si tenga presente che questa opzione è
supportata su NFS solo a partire da NFSv3 e con il kernel 2.6, nelle versioni
precedenti la funzionalità viene emulata controllando prima l'esistenza del
file per cui usarla per creare \index{file!di lock} un file di lock potrebbe
dar luogo a una \itindex{race~condition} \textit{race condition}.\footnote{un
  file potrebbe venir creato fra il controllo la successiva apertura con
  \const{O\_CREAT}, la cosa si può risolvere comunque creando un file con un
  nome univoco ed usando la funzione \func{link} per creare il \index{file!di
    lock} file di lock, (vedi sez.~\ref{sec:ipc_file_lock}).}

Se si usa \const{O\_EXCL} senza \const{O\_CREAT} il comportamento è
indefinito.  Nella creazione di un file con \const{O\_CREAT} occorre sempre
specificare l'argomento di \param{mode}, che altrimenti è ignorato. Si tenga
presente che indipendentemente dai permessi che si possono assegnare, che in
seguito potrebbero non consentire lettura o scrittura, quando il file viene
aperto l'accesso viene garantito secondo quanto richiesto con i flag di
tab.~\ref{tab:open_access_mode_flag}.  Quando viene creato un nuovo file
\const{O\_CREAT} con tutti e tre i tempi del file di
tab.~\ref{tab:file_file_times} vengono impostati al tempo corrente. Se invece
si tronca il file con \const{O\_TRUNC} verranno impostati soltanto il
\textit{modification time} e lo \textit{status change time}.

\begin{table}[!htb]
  \centering
  \footnotesize
    \begin{tabular}[c]{|l|p{10 cm}|}
      \hline
      \textbf{Flag} & \textbf{Significato} \\
      \hline
      \hline
      \const{O\_APPEND}  & Il file viene aperto in \itindex{append~mode}
                           \textit{append mode}. La posizione sul file (vedi
                           sez.~\ref{sec:file_lseek}) viene sempre mantenuta
                           sulla sua coda, per cui quanto si scrive
                           viene sempre aggiunto al contenuto precedente. Con
                           NFS questa funzionalità non è supportata 
                           e viene emulata, per questo possono verificarsi
                           \itindex{race~condition} \textit{race 
                             condition} con una sovrapposizione dei dati se
                           più di un processo scrive allo stesso tempo.\\
      \const{O\_ASYNC}   & Apre il file per l'I/O in modalità asincrona (vedi
                           sez.~\ref{sec:signal_driven_io}). Quando è
                           impostato viene generato il segnale \signal{SIGIO}
                           tutte le volte che il file è pronto per le
                           operazioni di lettura o scrittura. Questo flag si
                           può usare solo terminali, pseudo-terminali e socket
                           e, a partire dal kernel 2.6, anche sulle fifo. Per
                           un bug dell'implementazione non è opportuno usarlo
                           in fase di apertura del file, deve
                           invece essere attivato successivamente con
                           \func{fcntl}.\\
      \const{O\_CLOEXEC}&  Attiva la modalità di \itindex{close-on-exec}
                           \textit{close-on-exec} (vedi
                           sez.~\ref{sec:proc_exec}) sul file. Il flag è 
                           previsto dallo standard POSIX.1-2008, ed è stato
                           introdotto con il kernel 2.6.23 per evitare una
                           \itindex{race~condition} \textit{race condition}
                           che si potrebbe verificare con i \textit{thread}
                           fra l'apertura del file e l'impostazione della
                           suddetta modalità con \func{fcntl} (vedi
                           sez.~\ref{sec:file_fcntl_ioctl}).\\
      \const{O\_DIRECT}  & Esegue l'I/O direttamente dalla memoria in
                           \textit{user space} in maniera sincrona, in modo da
                           scavalcare i meccanismi di bufferizzazione del
                           kernel. Introdotto con il kernel 2.4.10 ed
                           utilizzabile soltanto se si è definita la 
                           macro \macro{\_GNU\_SOURCE}.\\ 
      \const{O\_NOATIME} & Blocca l'aggiornamento dei tempi di accesso dei
                           file (vedi sez.~\ref{sec:file_file_times}). Per
                           molti filesystem questa funzionalità non è
                           disponibile per il singolo file ma come opzione
                           generale da specificare in fase di
                           montaggio. Introdotto con il kernel 2.6.8 ed 
                           utilizzabile soltanto se si è definita la 
                           macro \macro{\_GNU\_SOURCE}.\\ 
      \const{O\_NONBLOCK}& Apre il file in \textsl{modalità non bloccante} per
                           le operazioni di I/O (vedi
                           sez.~\ref{sec:file_noblocking}). Questo significa
                           il fallimento delle successive operazioni di
                           lettura o scrittura qualora il file non sia pronto
                           per la loro esecuzione immediata, invece del 
                           blocco delle stesse in attesa di una successiva
                           possibilità di esecuzione come avviene
                           normalmente. Questa modalità ha senso solo per le
                           fifo, vedi sez.~\ref{sec:ipc_named_pipe}), o quando
                           si vuole aprire un file di dispositivo per eseguire
                           una \func{ioctl} (vedi
                           sez.~\ref{sec:file_fcntl_ioctl}).\\ 
      \const{O\_NDELAY}  & In Linux è un sinonimo di \const{O\_NONBLOCK}, ma
                           origina da SVr4, dove però causava il ritorno da
                           una \func{read} con un valore nullo e non con un
                           errore, questo introduce un'ambiguità, dato che
                           come vedremo in sez.~\ref{sec:file_read} il ritorno
                           di un valore nullo da parte di \func{read} ha 
                           il significato di una \textit{end-of-file}.\\
      \const{O\_SYNC}    & Apre il file per l'input/output sincrono. Ogni
                           scrittura si bloccherà fino alla conferma
                           dell'arrivo di tutti i dati e di tutti i metadati
                           sull'hardware sottostante (in questo significato
                           solo dal kernel 2.6.33).\\
      \const{O\_DSYNC}   & Apre il file per l'input/output sincrono. Ogni
                           scrittura di dati si bloccherà fino alla conferma
                           dell'arrivo degli stessi e della parte di metadati
                           ad essi relativa sull'hardware sottostante (in
                           questo significato solo dal kernel 2.6.33).\\
      \hline
    \end{tabular}
    \caption{Le costanti che identificano le \textit{modalità di operazione} di
      un file.} 
  \label{tab:open_operation_flag}
\end{table}

Il terzo gruppo è quello dei flag delle \textsl{modalità di operazione},
riportati in tab.~\ref{tab:open_operation_flag}, che permettono di specificare
varie caratteristiche del comportamento delle operazioni di I/O che verranno
eseguite sul file. Tutti questi, tranne \const{O\_CLOEXEC}, che viene
mantenuto per ogni singolo file descriptor, vengono salvati nel campo
\var{f\_flags} della struttura \kstruct{file} insieme al valore della
\textsl{modalità di accesso} andando far parte dei cosiddetti \textit{file
  status flags}. Il loro valore viene impostato alla chiamata di \func{open},
ma possono venire riletti in un secondo tempo con \func{fcntl}, inoltre alcuni
di essi possono anche essere modificati tramite questa funzione, con
conseguente effetto sulle caratteristiche operative che controllano (torneremo
sull'argomento in sez.~\ref{sec:file_fcntl_ioctl}).

Il flag \const{O\_ASYNC} (che, per per compatibilità con BSD, si può indicare
anche con la costante \const{FASYNC}) è definito come possibile valore per
\func{open}, ma per un bug dell'implementazione,\footnote{segnalato come
  ancora presente nella pagina di manuale almeno fino al Settembre 2011.} non
solo non attiva il comportamento citato, ma se usato richiede di essere
esplicitamente disattivato prima di essere attivato in maniera effettiva con
l'uso di \func{fcntl}. Per questo motivo, non essendovi nessuna necessità
specifica di definirlo in fase di apertura del file, è sempre opportuno
attivarlo in un secondo tempo con \func{fcntl} (vedi
sez.~\ref{sec:file_fcntl_ioctl}).

Il flag \const{O\_DIRECT} non è previsto da nessuno standard, anche se è
presente in alcuni kernel unix-like.\footnote{il flag è stato introdotto dalla
  SGI in IRIX, ma è presente senza limiti di allineamento dei buffer anche in
  FreeBSD.} Per i kernel della serie 2.4 si deve garantire che i buffer in
\textit{user space} da cui si effettua il trasferimento diretto dei dati siano
allineati alle dimensioni dei blocchi del filesystem. Con il kernel 2.6 in
genere basta che siano allineati a multipli di 512 byte, ma le restrizioni
possono variare a seconda del filesystem, ed inoltre su alcuni filesystem
questo flag può non essere supportato, nel qual caso si avrà un errore di
\errval{EINVAL}.

Lo scopo di \const{O\_DIRECT} è consentire un completo controllo sulla
bufferizzazione dei propri dati per quelle applicazioni (in genere database)
che hanno esigenze specifiche che non vengono soddisfatte nella maniera più
efficiente dalla politica generica utilizzata dal kernel. In genere l'uso di
questo flag peggiora le prestazioni tranne quando le applicazioni sono in
grado di ottimizzare la propria bufferizzazione in maniera adeguata. Se lo si
usa si deve avere cura di non mescolare questo tipo di accesso con quello
ordinario, in quante le esigenze di mantenere coerenti i dati porterebbero ad
un peggioramento delle prestazioni. Lo stesso dicasi per l'interazione con
eventuale mappatura in memoria del file (vedi sez.~\ref{sec:file_memory_map}).

Si tenga presente infine che anche se l'uso di \const{O\_DIRECT} comporta una
scrittura sincrona dei dati dei buffer in \textit{user space}, questo non è
completamente equivalente all'uso di \const{O\_SYNC} che garantisce anche
sulla scrittura sincrona dei metadati associati alla scrittura dei dati del
file.\footnote{la situazione si complica ulteriormente per NFS, in cui l'uso
  del flag disabilita la bufferizzazione solo dal lato del client, e può
  causare problemi di prestazioni.} Per questo in genere è opportuno se si usa
\const{O\_DIRECT} è opportuno richiedere anche \const{O\_SYNC}.

Si tenga presente infine che la implementazione di \const{O\_SYNC} di Linux
differisce da quanto previsto dallo standard POSIX.1 che prevede, oltre a
questo flag che dovrebbe indicare la sincronizzazione completa di tutti i dati
e di tutti i metadati, altri due flag \const{O\_DSYNC} e \const{O\_RSYNC}. 

Il primo dei due richiede la scrittura sincrona di tutti i dati del file e dei
metadati che ne consentono l'immediata rilettura, ma non di tutti i metadati,
per evitare la perdita di prestazioni relativa alla sincronizzazione di
informazioni ausiliarie come i tempi dei file.  Il secondo, da usare in
combinazione con \const{O\_SYNC} o \const{O\_DSYNC} ne sospende l'effetto,
consentendo al kernel di bufferizzare le scritture, ma soltanto finché non
avviene una lettura, in quel caso i dati ed i metadati dovranno essere
sincronizzati immediatamente (secondo le modalità indicate da \const{O\_SYNC}
e \const{O\_DSYNC}) e la lettura verrà bloccata fintanto che detta
sincronizzazione non sia completata.

Nel caso di Linux, fino al kernel 2.6.33, esisteva solo \const{O\_SYNC}, ma
con il comportamento previsto dallo standard per \const{O\_DSYNC}, e sia
questo che \const{O\_RSYNC} erano definiti (fin dal kernel 2.1.130) come
sinonimi di \const{O\_SYNC}.  Con il kernel 2.6.33 il significato di
\const{O\_SYNC} è diventato quello dello standard, ma gli è stato assegnato un
valore diverso, mantenendo quello originario, con il comportamento
corrispondete, per \const{O\_DSYNC} in modo che applicazioni compilate con
versioni precedenti delle librerie e del kernel non trovassero un
comportamento diverso.  Inoltre il nuovo \const{O\_SYNC} è stato definito in
maniera opportuna in modo che su versioni del kernel precedenti la 2.6.33
torni a corrispondere al valore di \const{O\_DSYNC}.

% NOTE: per le differenze fra O_DSYNC, O_SYNC e O_RSYNC introdotte nella  
% nello sviluppo del kernel 2.6.33, vedi http://lwn.net/Articles/350219/ 

Nelle prime versioni di Unix i valori di \param{flag} specificabili per
\func{open} erano solo quelli relativi alle modalità di accesso del file.  Per
questo motivo per creare un nuovo file c'era una \textit{system call}
apposita, \funcd{creat}, nel caso di Linux questo non è più necessario ma la
funzione è definita ugualmente; il suo prototipo è:

\begin{funcproto}{
\fhead{fcntl.h}
\fdecl{int creat(const char *pathname, mode\_t mode)}
\fdesc{Crea un nuovo file vuoto.} 
}

{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
  caso \var{errno} assumerà gli stessi valori che si otterrebbero con
  \func{open}.}
\end{funcproto}

La funzione crea un nuovo file vuoto, con i permessi specificati
dall'argomento \param{mode}. È del tutto equivalente a \code{open(filedes,
  O\_CREAT|O\_WRONLY|O\_TRUNC, mode)} e resta solo per compatibilità con i
vecchi programmi.

Una volta che l'accesso ad un file non sia più necessario la funzione di
sistema \funcd{close} permette di ``\textsl{chiuderlo}'', in questo modo il
file non sarà più accessibile ed il relativo file descriptor ritornerà
disponibile; il suo prototipo è:

\begin{funcproto}{
\fhead{unistd.h}
\fdecl{int close(int fd)}
\fdesc{Chiude un file.} 
}

{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
  caso \var{errno} assumerà uno dei valori: 
  \begin{errlist}
    \item[\errcode{EBADF}]  \param{fd} non è un descrittore valido.
    \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
  \end{errlist}
  ed inoltre \errval{EIO} nel suo significato generico.}
\end{funcproto}

La funzione chiude il file descriptor \param{fd}. La chiusura rilascia ogni
eventuale blocco (il \textit{file locking} \itindex{file~locking} è trattato
in sez.~\ref{sec:file_locking}) che il processo poteva avere acquisito su di
esso. Se \param{fd} è l'ultimo riferimento (di eventuali copie, vedi
sez.~\ref{sec:file_shared_access} e \ref{sec:file_dup}) ad un file aperto,
tutte le risorse nella \itindex{file~table} \textit{file table} vengono
rilasciate. Infine se il file descriptor era l'ultimo riferimento ad un file
su disco quest'ultimo viene cancellato.

Si ricordi che quando un processo termina tutti i suoi file descriptor vengono
automaticamente chiusi, molti programmi sfruttano questa caratteristica e non
usano esplicitamente \func{close}. In genere comunque chiudere un file senza
controllare lo stato di uscita di \func{close} un è errore; molti filesystem
infatti implementano la tecnica del cosiddetto \textit{write-behind}, per cui
una \func{write} può avere successo anche se i dati non sono stati
effettivamente scritti su disco. In questo caso un eventuale errore di I/O
avvenuto in un secondo tempo potrebbe sfuggire, mentre verrebbe riportato alla
chiusura esplicita del file. Per questo motivo non effettuare il controllo può
portare ad una perdita di dati inavvertita.\footnote{in Linux questo
  comportamento è stato osservato con NFS e le quote su disco.}

In ogni caso una \func{close} andata a buon fine non garantisce che i dati
siano stati effettivamente scritti su disco, perché il kernel può decidere di
ottimizzare l'accesso a disco ritardandone la scrittura. L'uso della funzione
\func{sync} (vedi sez.~\ref{sec:file_sync}) effettua esplicitamente il
\emph{flush} dei dati, ma anche in questo caso resta l'incertezza dovuta al
comportamento dell'hardware, che a sua volta può introdurre ottimizzazioni
dell'accesso al disco che ritardano la scrittura dei dati. Da questo deriva
l'abitudine di alcuni sistemisti di ripetere tre volte il comando omonimo
prima di eseguire lo shutdown di una macchina.


\subsection{La gestione della posizione nel file}
\label{sec:file_lseek}

Come già accennato in sez.~\ref{sec:file_fd} a ciascun file aperto è associata
una \textsl{posizione corrente nel file} (il cosiddetto \textit{file offset},
mantenuto nel campo \var{f\_pos} di \kstruct{file}) espressa da un numero
intero positivo che esprime il numero di byte dall'inizio del file. Tutte le
operazioni di lettura e scrittura avvengono a partire da questa posizione che
viene automaticamente spostata in avanti del numero di byte letti o scritti.

In genere, a meno di non avere richiesto la modalità \itindex{append~mode} di
\textit{append} con \const{O\_APPEND}, questa posizione viene impostata a zero
all'apertura del file. È possibile impostarla ad un valore qualsiasi con la
funzione di sistema \funcd{lseek}, il cui prototipo è:

\begin{funcproto}{
\fhead{sys/types.h}
\fhead{unistd.h}
\fdecl{off\_t lseek(int fd, off\_t offset, int whence)}
\fdesc{Imposta la posizione sul file.} 
}

{La funzione ritorna il valore della posizione sul file in caso di successo e
  $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei valori:
  \begin{errlist}
    \item[\errcode{EINVAL}] \param{whence} non è un valore valido.
    \item[\errcode{EOVERFLOW}] \param{offset} non può essere rappresentato nel
      tipo \type{off\_t}.
    \item[\errcode{ESPIPE}] \param{fd} è una pipe, un socket o una fifo.
  \end{errlist}
  ed inoltre \errval{EBADF} nel suo significato generico.}
\end{funcproto}

La funzione imposta la nuova posizione sul file usando il valore indicato
da \param{offset}, che viene sommato al riferimento dato
dall'argomento \param{whence}, che deve essere indicato con una delle costanti
riportate in tab.~\ref{tab:lseek_whence_values}.\footnote{per compatibilità
  con alcune vecchie notazioni questi valori possono essere rimpiazzati
  rispettivamente con 0, 1 e 2 o con \const{L\_SET}, \const{L\_INCR} e
  \const{L\_XTND}.} Si tenga presente che la chiamata a \func{lseek} non causa
nessun accesso al file, si limita a modificare la posizione corrente (cioè il
campo \var{f\_pos} della struttura \kstruct{file}, vedi
fig.~\ref{fig:file_proc_file}).  Dato che la funzione ritorna la nuova
posizione, usando il valore zero per \param{offset} si può riottenere la
posizione corrente nel file con \code{lseek(fd, 0, SEEK\_CUR)}.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Costante} & \textbf{Significato} \\
    \hline
    \hline
    \const{SEEK\_SET} & Si fa riferimento all'inizio del file: il valore, che 
                        deve essere positivo, di \param{offset} indica
                        direttamente la nuova posizione corrente.\\
    \const{SEEK\_CUR} & Si fa riferimento alla posizione corrente del file:
                        ad essa viene sommato \param{offset}, che può essere
                        negativo e positivo, per ottenere la nuova posizione
                        corrente.\\
    \const{SEEK\_END} & Si fa riferimento alla fine del file: alle dimensioni
                        del file viene sommato \param{offset}, che può essere
                        negativo e positivo, per ottenere la nuova posizione
                        corrente.\\
    \hline
    \const{SEEK\_DATA}& Sposta la posizione nel file sull'inizio del primo
                        blocco di dati dopo un \textit{hole} che segue (o
                        coincide) con la posizione indicata da \param{offset}
                        (dal kernel 3.1).\\
    \const{SEEK\_HOLE}& Sposta la posizione sul file all'inizio del primo
                        \textit{hole} nel file che segue o inizia
                        con \param{offset}, oppure si porta su \param{offset} 
                        se questo è all'interno di un \textit{hole}, oppure si
                        porta alla fine del file se non ci sono \textit{hole}
                        dopo \param{offset} (dal kernel 3.1).\\ 
    \hline
  \end{tabular}  
  \caption{Possibili valori per l'argomento \param{whence} di \func{lseek}.} 
  \label{tab:lseek_whence_values}
\end{table}


% NOTE: per SEEK_HOLE e SEEK_DATA, inclusi nel kernel 3.1, vedi
% http://lwn.net/Articles/439623/ 

Si tenga presente inoltre che usare \const{SEEK\_END} non assicura affatto che
la successiva scrittura avvenga alla fine del file, infatti se questo è stato
aperto anche da un altro processo che vi ha scritto, la fine del file può
essersi spostata, ma noi scriveremo alla posizione impostata in precedenza
(questa è una potenziale sorgente di \itindex{race~condition} \textit{race
  condition}, vedi sez.~\ref{sec:file_shared_access}).

Non tutti i file supportano la capacità di eseguire una \func{lseek}, in
questo caso la funzione ritorna l'errore \errcode{ESPIPE}. Questo, oltre che
per i tre casi citati nel prototipo, vale anche per tutti quei dispositivi che
non supportano questa funzione, come ad esempio per i file di
terminale.\footnote{altri sistemi, usando \const{SEEK\_SET}, in questo caso
  ritornano il numero di caratteri che vi sono stati scritti.} Lo standard
POSIX però non specifica niente in proposito. Inoltre alcuni
\index{file!speciali} file speciali, ad esempio \file{/dev/null}, non causano
un errore ma restituiscono un valore indefinito.

\itindbeg{sparse~file} 

Infine si tenga presente che, come accennato in sez.~\ref{sec:file_file_size},
con \func{lseek} è possibile impostare una posizione anche oltre la corrente
fine del file. In tal caso alla successiva scrittura il file sarà esteso a
partire da detta posizione, con la creazione di quello che viene chiamato
\index{file!\textit{hole}} ``\textsl{buco}'' (in gergo \textit{hole}) nel
file.  Il nome deriva dal fatto che nonostante la dimensione del file sia
cresciuta in seguito alla scrittura effettuata, lo spazio vuoto fra la
precedente fine del file ed la nuova parte scritta dopo lo spostamento non
corrisponde ad una allocazione effettiva di spazio su disco, che sarebbe
inutile dato che quella zona è effettivamente vuota.

Questa è una delle caratteristiche specifiche della gestione dei file di un
sistema unix-like e si dice che il file in questione è uno \textit{sparse
  file}. In sostanza, se si ricorda la struttura di un filesystem illustrata
in fig.~\ref{fig:file_filesys_detail}, quello che accade è che \itindex{inode}
nell'\textit{inode} del file viene segnata l'allocazione di un blocco di dati
a partire dalla nuova posizione, ma non viene allocato nulla per le posizioni
intermedie; in caso di lettura sequenziale del contenuto del file il kernel si
accorgerà della presenza del buco, e restituirà degli zeri come contenuto di
quella parte del file.

Questa funzionalità comporta una delle caratteristiche della gestione dei file
su Unix che spesso genera più confusione in chi non la conosce, per cui
sommando le dimensioni dei file si può ottenere, se si hanno molti
\textit{sparse file}, un totale anche maggiore della capacità del proprio
disco e comunque maggiore della dimensione che riporta un comando come
\cmd{du}, che calcola lo spazio disco occupato in base al numero dei blocchi
effettivamente allocati per il file.

Questo avviene proprio perché in un sistema unix-like la dimensione di un file
è una caratteristica del tutto indipendente dalla quantità di spazio disco
effettivamente allocato, e viene registrata \itindex{inode}
sull'\textit{inode} come le altre proprietà del file. La dimensione viene
aggiornata automaticamente quando si estende un file scrivendoci, e viene
riportata dal campo \var{st\_size} di una struttura \struct{stat} quando si
effettua la chiamata ad una delle funzioni \texttt{*stat} viste in
sez.~\ref{sec:file_stat}.

Questo comporta che in generale, fintanto che lo si è scritto sequenzialmente,
la dimensione di un file sarà più o meno corrispondente alla quantità di
spazio disco da esso occupato, ma esistono dei casi, come questo in cui ci si
sposta in una posizione oltre la fine corrente del file, o come quello
accennato in in sez.~\ref{sec:file_file_size} in cui si estende la dimensione
di un file con una \func{truncate}, in cui in sostanza si modifica il valore
della dimensione di \var{st\_size} senza allocare spazio su disco. Questo
consente di creare inizialmente file di dimensioni anche molto grandi, senza
dover occupare da subito dello spazio disco che in realtà sarebbe
inutilizzato.

\itindend{sparse~file}

A partire dal kernel 3.1, riprendendo una interfaccia adottata su Solaris,
sono state aggiunti due nuovi valori per l'argomento \param{whence}, riportati
nella seconda sezione di tab.~\ref{tab:lseek_whence_values}, che consentono di
riconoscere la presenza di \index{file!\textit{hole}} \textit{hole}
all'interno dei file ad uso di quelle applicazioni (come i programmi di
backup) che possono salvare spazio disco nella copia degli \textit{sparse
  file}. Una applicazione può così determinare la presenza di un
\index{file!\textit{hole}} \textit{hole} usando \const{SEEK\_HOLE} all'inizio
del file e determinare poi l'inizio della successiva sezione di dati usando
\const{SEEK\_DATA}. Per compatibilità con i filesystem che non supportano
questa funzionalità è previsto comunque che in tal caso \const{SEEK\_HOLE}
riporti sempre la fine del file e \const{SEEK\_DATA} il valore
di \param{offset}.

Inoltre la decisione di come riportare (o di non riportare) la presenza di un
\index{file!\textit{hole}} buco in un file è lasciata all'implementazione del
filesystem, dato che esistono vari motivi per cui una sezione di un file può
non contenere dati ed essere riportata come tale (ad esempio può essere stata
preallocata con \func{fallocate}, vedi sez.~\ref{sec:file_fadvise}) oltre a
quelle classiche appena esposte. Questo significa che l'uso di questi nuovi
valori non garantisce la mappatura della effettiva allocazione dello spazio
disco di un file, per il quale esiste una specifica operazione di controllo
(vedi sez.~\ref{sec:file_fcntl_ioctl}).



\subsection{Le funzioni per la lettura di un file}
\label{sec:file_read}

Una volta che un file è stato aperto (con il permesso in lettura) si possono
leggere i dati che contiene utilizzando la funzione di sistema \funcd{read},
il cui prototipo è:

\begin{funcproto}{
\fhead{unistd.h}
\fdecl{ssize\_t read(int fd, void * buf, size\_t count)}
\fdesc{Legge i dati da un file.} 
}

{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
  caso \var{errno} assumerà uno dei valori: 
  \begin{errlist}
  \item[\errcode{EAGAIN}] la funzione non ha nessun dato da restituire e si è
    aperto il file con \const{O\_NONBLOCK}.
  \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
  \item[\errcode{EINVAL}] \param{fd} è associato ad un oggetto non leggibile,
    o lo si è ottenuto da \func{timerfd\_create} (vedi
    sez.~\ref{sec:sig_signalfd_eventfd}) e si è usato un valore sbagliato
    per \param{size} o si è usato \const{O\_DIRECT} ed il buffer non è
    allineato.
  \item[\errval{EIO}] si è tentata la lettura dal terminale di controllo
    essendo in background (vedi sez.~\ref{sec:term_io_design}).
  \end{errlist}
  ed inoltre \errval{EBADF}, \errval{EFAULT} e \errval{EISDIR}, nel loro
  significato generico.}
\end{funcproto}

La funzione tenta di leggere \param{count} byte dal file \param{fd} a partire
dalla posizione corrente, scrivendoli nel buffer \param{buf}. Dopo la lettura
la posizione sul file è spostata automaticamente in avanti del numero di byte
letti. Se \param{count} è zero la funzione restituisce zero senza nessun altro
risultato. Inoltre che non è detto che la funzione \func{read} restituisca il
numero di byte richiesto, ci sono infatti varie ragioni per cui la funzione
può restituire un numero di byte inferiore: questo è un comportamento normale,
e non un errore, che bisogna sempre tenere presente.

La prima e più ovvia di queste ragioni è che si è chiesto di leggere più byte
di quanto il file ne contenga. In questo caso il file viene letto fino alla
sua fine, e la funzione ritorna regolarmente il numero di byte letti
effettivamente. Raggiunta la fine del file, alla ripetizione di un'operazione
di lettura, otterremmo il ritorno immediato di \func{read} con uno zero.  La
condizione di raggiungimento della fine del file non è un errore, e viene
segnalata appunto da un valore di ritorno di \func{read} nullo. Ripetere
ulteriormente la lettura non avrebbe nessun effetto se non quello di
continuare a ricevere zero come valore di ritorno.

Con i \textsl{file regolari} questa è l'unica situazione in cui si può avere
un numero di byte letti inferiore a quello richiesto, ma questo non è vero
quando si legge da un terminale, da una fifo o da una pipe. In tal caso
infatti, se non ci sono dati in ingresso, la \func{read} si blocca (a meno di
non aver selezionato la modalità non bloccante, vedi
sez.~\ref{sec:file_noblocking}) e ritorna solo quando ne arrivano; se il numero
di byte richiesti eccede quelli disponibili la funzione ritorna comunque, ma
con un numero di byte inferiore a quelli richiesti.

Lo stesso comportamento avviene caso di lettura dalla rete (cioè su un socket,
come vedremo in sez.~\ref{sec:sock_io_behav}), o per la lettura da certi file
di dispositivo, come le unità a nastro, che restituiscono sempre i dati ad un
singolo blocco alla volta, o come le linee seriali, che restituiscono solo i
dati ricevuti fino al momento della lettura, o i terminali, per i quali si
applicano inoltre ulteriori condizioni che approfondiremo in
sez.~\ref{sec:sess_terminal_io}.

Infine anche le due condizioni segnalate dagli errori \errcode{EINTR} ed
\errcode{EAGAIN} non sono propriamente degli errori. La prima si verifica
quando la \func{read} è bloccata in attesa di dati in ingresso e viene
interrotta da un segnale. In tal caso l'azione da intraprendere è quella di
rieseguire la funzione, torneremo in dettaglio sull'argomento in
sez.~\ref{sec:sig_gen_beha}.  La seconda si verifica quando il file è aperto
in modalità non bloccante (con \const{O\_NONBLOCK}) e non ci sono dati in
ingresso: la funzione allora ritorna immediatamente con un errore
\errcode{EAGAIN}\footnote{in BSD si usa per questo errore la costante
  \errcode{EWOULDBLOCK}, in Linux, con la \acr{glibc}, questa è sinonima di
  \errcode{EAGAIN}, ma se si vuole essere completamente portabili occorre
  verificare entrambi i valori, dato che POSIX.1-2001 non richiede che siano
  coincidenti.} che indica soltanto che non essendoci al momento dati
disponibili occorre provare a ripetere la lettura in un secondo tempo,
torneremo sull'argomento in sez.~\ref{sec:file_noblocking}.

La funzione \func{read} è una delle \textit{system call} fondamentali,
esistenti fin dagli albori di Unix, ma nella seconda versione delle
\textit{Single Unix Specification}\footnote{questa funzione, e l'analoga
  \func{pwrite} sono state aggiunte nel kernel 2.1.60, il supporto nelle
  \acr{glibc}, compresa l'emulazione per i vecchi kernel che non hanno la
  \textit{system call}, è stato aggiunto con la versione 2.1, in versioni
  precedenti sia del kernel che delle librerie la funzione non è disponibile.}
(quello che viene chiamato normalmente Unix98, vedi
sez.~\ref{sec:intro_xopen}) è stata introdotta la definizione di un'altra
funzione di sistema, \funcd{pread}, il cui prototipo è:

\begin{funcproto}{
\fhead{unistd.h}
\fdecl{ssize\_t pread(int fd, void * buf, size\_t count, off\_t offset)}
\fdesc{Legge a partire da una posizione sul file.} 
}

{La funzione ritorna il numero di byte letti in caso di successo e $-1$ per un
  errore, nel qual caso \var{errno} assumerà i valori già visti per
  \func{read} e \func{lseek}.}
\end{funcproto}

La funzione prende esattamente gli stessi argomenti di \func{read} con lo
stesso significato, a cui si aggiunge l'argomento \param{offset} che indica
una posizione sul file. Identico è il comportamento ed il valore di
ritorno. La funzione serve quando si vogliono leggere dati dal file senza
modificare la posizione corrente.

L'uso di \func{pread} è equivalente all'esecuzione di una \func{read} seguita
da una \func{lseek} che riporti al valore precedente la posizione corrente sul
file, ma permette di eseguire l'operazione atomicamente. Questo può essere
importante quando la posizione sul file viene condivisa da processi diversi
(vedi sez.~\ref{sec:file_shared_access}).  Il valore di
\param{offset} fa sempre riferimento all'inizio del file.

La funzione \func{pread} è disponibile anche in Linux, però diventa
accessibile solo attivando il supporto delle estensioni previste dalle
\textit{Single Unix Specification} con la definizione della macro:
\begin{Example}
#define _XOPEN_SOURCE 500
\end{Example}
e si ricordi di definire questa macro prima dell'inclusione del file di
dichiarazioni \headfile{unistd.h}.



\subsection{Le funzioni per la scrittura di un file}
\label{sec:file_write}

Una volta che un file è stato aperto (con il permesso in scrittura) si può
scrivere su di esso utilizzando la funzione di sistema \funcd{write}, il cui
prototipo è:

\begin{funcproto}{
\fhead{unistd.h}
\fdecl{ssize\_t write(int fd, void * buf, size\_t count)}
\fdesc{Scrive i dati su un file.} 
}

{La funzione ritorna il numero di byte scritti in caso di successo e $-1$ per
  un errore, nel qual caso \var{errno} assumerà uno dei valori:
  \begin{errlist}
  \item[\errcode{EAGAIN}] ci si sarebbe bloccati, ma il file era aperto in
    modalità \const{O\_NONBLOCK}.
  \item[\errcode{EFBIG}] si è cercato di scrivere oltre la dimensione massima
    consentita dal filesystem o il limite per le dimensioni dei file del
    processo o su una posizione oltre il massimo consentito.
  \item[\errcode{EINTR}] si è stati interrotti da un segnale prima di aver
    potuto scrivere qualsiasi dato.
  \item[\errcode{EINVAL}] \param{fd} è connesso ad un oggetto che non consente
    la scrittura o si è usato \const{O\_DIRECT} ed il buffer non è allineato.
  \item[\errcode{EPIPE}] \param{fd} è connesso ad una pipe il cui altro capo è
    chiuso in lettura; in questo caso viene anche generato il segnale
    \signal{SIGPIPE}, se questo viene gestito (o bloccato o ignorato) la
    funzione ritorna questo errore.
  \end{errlist}
  ed inoltre \errval{EBADF}, \errval{EFAULT}, \errval{EIO}, \errval{EISDIR},
  \errval{ENOSPC} nel loro significato generico.}
\end{funcproto}


Come nel caso di \func{read} la funzione tenta di scrivere \param{count} byte
a partire dalla posizione corrente nel file e sposta automaticamente la
posizione in avanti del numero di byte scritti. Se il file è aperto in
modalità \itindex{append~mode} \const{O\_APPEND} i dati vengono sempre scritti
alla fine del file.  Lo standard POSIX richiede che i dati scritti siano
immediatamente disponibili ad una \func{read} chiamata dopo che la
\func{write} che li ha scritti è ritornata; ma dati i meccanismi di caching
non è detto che tutti i filesystem supportino questa capacità.

Se \param{count} è zero la funzione restituisce zero senza fare nient'altro.
Per i file ordinari il numero di byte scritti è sempre uguale a quello
indicato da \param{count}, a meno di un errore. Negli altri casi si ha lo
stesso comportamento di \func{read}.

Anche per \func{write} lo standard Unix98 definisce un'analoga \funcd{pwrite}
per scrivere alla posizione indicata senza modificare la posizione corrente
nel file, il suo prototipo è:

\begin{funcproto}{
\fhead{unistd.h}
\fdecl{ssize\_t pwrite(int fd, void * buf, size\_t count, off\_t offset)}
\fdesc{Scrive a partire da una posizione sul file.} 
}

{La funzione ritorna il numero di byte letti in caso di successo e $-1$ per un
  errore, nel qual caso \var{errno} assumerà i valori già visti per
  \func{write} e \func{lseek}.}
\end{funcproto}

\noindent e per essa valgono le stesse considerazioni fatte per \func{pread}.


\section{Caratteristiche avanzate}
\label{sec:file_adv_func}

In questa sezione approfondiremo alcune delle caratteristiche più sottili
della gestione file in un sistema unix-like, esaminando in dettaglio il
comportamento delle funzioni base, inoltre tratteremo le funzioni che
permettono di eseguire alcune operazioni avanzate con i file (il grosso
dell'argomento sarà comunque affrontato in cap.~\ref{cha:file_advanced}).


\subsection{La gestione dell'accesso concorrente ai files}
\label{sec:file_shared_access}

In sez.~\ref{sec:file_fd} abbiamo descritto brevemente l'architettura
dell'interfaccia con i file da parte di un processo, mostrando in
fig.~\ref{fig:file_proc_file} le principali strutture usate dal kernel;
esamineremo ora in dettaglio le conseguenze che questa architettura ha nei
confronti dell'accesso concorrente allo stesso file da parte di processi
diversi.

\begin{figure}[!htb]
  \centering
  \includegraphics[width=12cm]{img/filemultacc}
  \caption{Schema dell'accesso allo stesso file da parte di due processi 
    diversi}
  \label{fig:file_mult_acc}
\end{figure}

Il primo caso è quello in cui due processi diversi aprono lo stesso file su
disco; sulla base di quanto visto in sez.~\ref{sec:file_fd} avremo una
situazione come quella illustrata in fig.~\ref{fig:file_mult_acc}: ciascun
processo avrà una sua voce nella \textit{file table} referenziata da un
diverso file descriptor nella sua \kstruct{file\_struct}. Entrambe le voci
nella \itindex{file~table} \textit{file table} faranno però riferimento allo
stesso \itindex{inode} \textit{inode} su disco.

Questo significa che ciascun processo avrà la sua posizione corrente sul file,
la sua modalità di accesso e versioni proprie di tutte le proprietà che
vengono mantenute nella sua voce della \itindex{file~table} \textit{file
  table}. Questo ha conseguenze specifiche sugli effetti della possibile
azione simultanea sullo stesso file, in particolare occorre tenere presente
che:
\begin{itemize}
\item ciascun processo può scrivere indipendentemente, dopo ciascuna
  \func{write} la posizione corrente sarà cambiata solo nel processo
  scrivente. Se la scrittura eccede la dimensione corrente del file questo
  verrà esteso automaticamente con l'aggiornamento del campo \var{i\_size}
  della struttura \kstruct{inode}.
\item se un file è in modalità \itindex{append~mode} \const{O\_APPEND} tutte
  le volte che viene effettuata una scrittura la posizione corrente viene
  prima impostata alla dimensione corrente del file letta dalla struttura
  \kstruct{inode}. Dopo la scrittura il file viene automaticamente esteso.
\item l'effetto di \func{lseek} è solo quello di cambiare il campo
  \var{f\_pos} nella struttura \kstruct{file} della \itindex{file~table}
  \textit{file table}, non c'è nessuna operazione sul file su disco. Quando la
  si usa per porsi alla fine del file la posizione viene impostata leggendo la
  dimensione corrente dalla struttura \kstruct{inode}.
\end{itemize}

\begin{figure}[!htb]
  \centering
  \includegraphics[width=12cm]{img/fileshar}
  \caption{Schema dell'accesso ai file da parte di un processo figlio}
  \label{fig:file_acc_child}
\end{figure}

Il secondo caso è quello in cui due file descriptor di due processi diversi
puntino alla stessa voce nella \itindex{file~table} \textit{file table}.
Questo è ad esempio il caso dei file aperti che vengono ereditati dal processo
figlio all'esecuzione di una \func{fork} (si ricordi quanto detto in
sez.~\ref{sec:proc_fork}). La situazione è illustrata in
fig.~\ref{fig:file_acc_child}; dato che il processo figlio riceve una copia
dello spazio di indirizzi del padre, riceverà anche una copia di
\kstruct{file\_struct} e della relativa tabella dei file aperti.

Questo significa che il figlio avrà gli stessi file aperti del padre, in
quanto la sua \kstruct{file\_struct}, pur essendo allocata in maniera
indipendente, contiene gli stessi valori di quella del padre e quindi i suoi
file descriptor faranno riferimento alla stessa voce nella
\itindex{file~table} \textit{file table}, condividendo così la posizione
corrente sul file. Questo ha le conseguenze descritte a suo tempo in
sez.~\ref{sec:proc_fork}: in caso di scrittura o lettura da parte di uno dei
due processi, la posizione corrente nel file varierà per entrambi, in quanto
verrà modificato il campo \var{f\_pos} della struttura \kstruct{file}, che è
la stessa per entrambi. Questo consente una sorta di
``\textsl{sincronizzazione}'' automatica della posizione sul file fra padre e
figlio che occorre tenere presente.

Si noti inoltre che in questo caso anche i \itindex{file~status~flag} flag di
stato del file, essendo mantenuti nella struttura \kstruct{file} della
\textit{file table}, vengono condivisi, per cui una modifica degli stessi con
\func{fcntl} (vedi sez.~\ref{sec:file_fcntl_ioctl}) si applicherebbe a tutti
processi che condividono la voce nella \itindex{file~table} \textit{file
  table}. Ai file però sono associati anche altri flag, dei quali l'unico
usato al momento è \const{FD\_CLOEXEC}, detti \itindex{file~descriptor~flags}
\textit{file descriptor flags}; questi invece sono mantenuti in
\kstruct{file\_struct}, e perciò sono locali per ciascun processo e non
vengono modificati dalle azioni degli altri anche in caso di condivisione
della stessa voce della \itindex{file~table} \textit{file table}.

Si tenga presente dunque che in un sistema unix-like è sempre possibile per
più processi accedere in contemporanea allo stesso file e che non esistono, a
differenza di altri sistemi operativi, dei meccanismi di blocco o di
restrizione dell'accesso impliciti se più processi vogliono accedere allo
stesso file. Questo significa che le operazioni di lettura e scrittura vengono
sempre fatte da ogni processo in maniera autonoma, utilizzando una posizione
corrente nel file che normalmente (a meno di non trovarsi nella situazione di
fig.~\ref{fig:file_acc_child}) è locale a ciascuno di essi.

Dal punto di vista della lettura dei dati questo comporta la possibilità di
poter leggere dati non coerenti in caso di scrittura contemporanea da parte di
un altro processo. Dal punto di vista della scrittura invece si potranno avere
sovrapposizioni imprevedibili quando due processi scrivono nella stessa
sezione di file, dato che ciascuno lo farà in maniera indipendente.  Il
sistema però fornisce in alcuni casi la possibilità di eseguire alcune
operazioni di scrittura in maniera coordinata anche senza utilizzare dei
meccanismi di sincronizzazione espliciti come il \itindex{file~locking}
\textit{file locking}, che esamineremo in sez.~\ref{sec:file_locking}.

Un caso tipico di necessità di accesso condiviso in scrittura è quello in cui
vari processi devono scrivere alla fine di un file (ad esempio un file di
log). Come accennato in sez.~\ref{sec:file_lseek} impostare la posizione alla
fine del file e poi scrivere può condurre ad una \itindex{race~condition}
\textit{race condition}l infatti può succedere che un secondo processo scriva
alla fine del file fra la \func{lseek} e la \func{write}. In questo caso, come
abbiamo appena visto, il file sarà esteso, ma il primo processo, che avrà la
posizione corrente che aveva impostato con la \func{lseek} che non corrisponde
più alla fine del file, e la sua successiva \func{write} sovrascriverà i dati
del secondo processo.

Il problema deriva dal fatto che usare due \textit{system call} in successione
non è mai un'operazione atomica dato che il kernel può interrompere
l'esecuzione del processo fra le due. Nel caso specifico il problema è stato
risolto introducendo la modalità di scrittura \itindex{append~mode} in
\textit{append}, attivabile con il flag \const{O\_APPEND}. In questo caso
infatti, come abbiamo illustrato in sez.~\ref{sec:file_open_close}, è il
kernel che aggiorna automaticamente la posizione alla fine del file prima di
effettuare la scrittura, e poi estende il file.  Tutto questo avviene
all'interno di una singola \textit{system call}, la \func{write}, che non
essendo interrompibile da un altro processo realizza un'operazione atomica.


\subsection{La duplicazione dei file descriptor}
\label{sec:file_dup}

Abbiamo già visto in sez.~\ref{sec:file_shared_access} come un processo figlio
condivida gli stessi file descriptor del padre; è possibile però ottenere un
comportamento analogo all'interno di uno stesso processo \textit{duplicando}
un file descriptor. Per far questo si usa la funzione di sistema \funcd{dup},
il cui prototipo è:

\begin{funcproto}{
\fhead{unistd.h}
\fdecl{int dup(int oldfd)}
\fdesc{Crea un file descriptor duplicato.} 
}

{La funzione ritorna il nuovo file descriptor in caso di successo e $-1$ per
  un errore, nel qual caso \var{errno} assumerà uno dei valori:
  \begin{errlist}
  \item[\errcode{EBADF}] \param{oldfd} non è un file aperto.
  \item[\errcode{EMFILE}] si è raggiunto il numero massimo consentito di file
    descriptor aperti.
  \end{errlist}
}  
\end{funcproto}

La funzione ritorna, come \func{open}, il primo file descriptor libero. Il
file descriptor è una copia esatta del precedente ed entrambi possono essere
interscambiati nell'uso. Per capire meglio il funzionamento della funzione si
può fare riferimento a fig.~\ref{fig:file_dup}. L'effetto della funzione è
semplicemente quello di copiare il valore di un certo file descriptor in
un altro all'interno della struttura \kstruct{file\_struct}, cosicché anche
questo faccia riferimento alla stessa voce nella \textit{file table}. Per
questo motivo si dice che il nuovo file descriptor è ``\textsl{duplicato}'',
da cui il nome della funzione.

\begin{figure}[!htb]
  \centering \includegraphics[width=12cm]{img/filedup}
  \caption{Schema dell'accesso ai file duplicati}
  \label{fig:file_dup}
\end{figure}

Si noti che per quanto illustrato in fig.~\ref{fig:file_dup} i file descriptor
duplicati condivideranno eventuali lock (vedi sez.~\ref{sec:file_locking}),
\itindex{file~status~flag} i flag di stato, e la posizione corrente sul
file. Se ad esempio si esegue una \func{lseek} per modificare la posizione su
uno dei due file descriptor, essa risulterà modificata anche sull'altro, dato
che quello che viene modificato è lo stesso campo nella voce della
\textit{file table} a cui entrambi fanno riferimento. 

L'unica differenza fra due file descriptor duplicati è che ciascuno avrà un
suo \textit{file descriptor flag} indipendente. A questo proposito deve essere
tenuto presente che nel caso in cui si usi \func{dup} per duplicare un file
descriptor, se questo ha il flag di \textit{close-on-exec}
\itindex{close-on-exec} attivo (vedi sez.~\ref{sec:proc_exec} e
sez.~\ref{sec:file_fcntl_ioctl}), questo verrà cancellato nel file descriptor
restituito come copia.

L'uso principale di questa funzione è nella shell per la redirezione dei file
standard di tab.~\ref{tab:file_std_files} fra l'esecuzione di una \func{fork}
e la successiva \func{exec}. Diventa così possibile associare un file (o una
pipe) allo \itindex{standard~input} \textit{standard input} o allo
\itindex{standard~output} \textit{standard output} (vedremo un esempio in
sez.~\ref{sec:ipc_pipe_use}, quando tratteremo le pipe). 

Ci si può chiedere perché non sia in questo caso sufficiente chiudere il file
standard che si vuole redirigere e poi aprire direttamente con \func{open} il
file vi si vuole far corrispondere, invece di duplicare un file descriptor che
si è già aperto. La risposta sta nel fatto che il file che si vuole redirigere
non è detto sia un file regolare, ma potrebbe essere, come accennato, anche
una fifo o un socket, oppure potrebbe essere un file associato ad un file
descriptor che si è ereditato già aperto (ad esempio attraverso un'altra
\func{exec}) da un processo antenato del padre, del quale non si conosce il
nome. Operando direttamente con i file descriptor \func{dup} consente di
ignorare le origini del file descriptor che si duplica e funziona in maniera
generica indipendentemente dall'oggetto a cui questo fa riferimento.

Per ottenere la redirezione occorre pertanto disporre del file descriptor
associato al file che si vuole usare e chiudere il file descriptor che si
vuole sostituire, cosicché esso possa esser restituito alla successiva
chiamata di \func{dup} come primo file descriptor disponibile.  Dato che
questa è l'operazione più comune, è prevista un'altra funzione di sistema,
\funcd{dup2}, che permette di specificare esplicitamente qual è il numero di
file descriptor che si vuole ottenere come duplicato; il suo prototipo è:

\begin{funcproto}{
\fhead{unistd.h}
\fdecl{int dup2(int oldfd, int newfd)}
\fdesc{Duplica un file descriptor su un altro.} 
}

{La funzione ritorna il nuovo file descriptor in caso di successo e $-1$ per
  un errore, nel qual caso \var{errno} assumerà uno dei valori:
  \begin{errlist}
  \item[\errcode{EBADF}] \param{oldfd} non è un file aperto o \param{newfd} ha
    un valore fuori dall'intervallo consentito per i file descriptor.
  \item[\errcode{EBUSY}] si è rilevata la possibilità di una
    \itindex{race~condition} \textit{race condition}.
  \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
  \item[\errcode{EMFILE}] si è raggiunto il numero massimo consentito di file
    descriptor aperti.
  \end{errlist}
}  
\end{funcproto}

La funzione duplica il file descriptor \param{oldfd} su un altro file
descriptor di valore \param{newfd}. Qualora il file descriptor \param{newfd}
sia già aperto, come avviene ad esempio nel caso della duplicazione di uno dei
file standard di tab.~\ref{tab:file_std_files}, esso sarà prima chiuso e poi
duplicato. Se \param{newfd} è uguale a \param{oldfd} la funzione non fa nulla
e si limita a restituire \param{newfd}.

L'uso di \func{dup2} ha vari vantaggi rispetto alla combinazione di
\func{close} e \func{dup}; anzitutto se \param{oldfd} è uguale \param{newfd}
questo verrebbe chiuso e \func{dup} fallirebbe, ma soprattutto l'operazione è
atomica e consente di evitare una \itindex{race~condition} \textit{race
  condition} in cui dopo la chiusura del file si potrebbe avere la ricezione
di un segnale il cui gestore (vedi sez.~\ref{sec:sig_signal_handler}) potrebbe
a sua volta aprire un file, per cui alla fine \func{dup} restituirebbe un file
descriptor diverso da quello voluto.

Con Linux inoltre la funzione prevede la possibilità di restituire l'errore
\errcode{EBUSY}, che non è previsto dallo standard, quando viene rilevata la
possibilità di una \itindex{race~condition} \textit{race condition} interna in
cui si cerca di duplicare un file descriptor che è stato allocato ma per il
quale non sono state completate le operazioni di apertura.\footnote{la
  condizione è abbastanza peculiare e non attinente al tipo di utilizzo
  indicato, quanto piuttosto ad un eventuale tentativo di duplicare file
  descriptor non ancora aperti, la condizione di errore non è prevista dallo
  standard, ma in condizioni simili FreeBSD risponde con un errore di
  \errval{EBADF}, mentre OpenBSD elimina la possibilità di una \textit{race
    condition} al costo di una perdita di prestazioni.} In tal caso occorre
ritentare l'operazione.

La duplicazione dei file descriptor può essere effettuata anche usando la
funzione di controllo dei file \func{fcntl} (che esamineremo in
sez.~\ref{sec:file_fcntl_ioctl}) con il parametro \const{F\_DUPFD}.
L'operazione ha la sintassi \code{fcntl(oldfd, F\_DUPFD, newfd)} e se si usa 0
come valore per \param{newfd} diventa equivalente a \func{dup}.  La sola
differenza fra le due funzioni (a parte la sintassi ed i diversi codici di
errore) è che \func{dup2} chiude il file descriptor \param{newfd} se questo è
già aperto, garantendo che la duplicazione sia effettuata esattamente su di
esso, invece \func{fcntl} restituisce il primo file descriptor libero di
valore uguale o maggiore di \param{newfd}, per cui se \param{newfd} è aperto
la duplicazione avverrà su un altro file descriptor.

Su Linux inoltre è presente una terza funzione di sistema non
standard,\footnote{la funzione è stata introdotta con il kernel 2.6.27 e resa
  disponibile con la \acr{glibc} 2.9.} \funcd{dup3}, che consente di duplicare
un file descriptor reimpostandone i flag, per usarla occorre definire la macro
\macro{\_GNU\_SOURCE} ed il suo prototipo è:

\begin{funcproto}{
\fhead{unistd.h}
\fdecl{int dup3(int oldfd, int newfd, int flags)}
\fdesc{Duplica un file descriptor su un altro.} 
}

{La funzione ritorna il nuovo file descriptor in caso di successo e $-1$ per
  un errore, nel qual caso \var{errno} assumerà gli stessi valori di
  \func{dup2} più \errcode{EINVAL} qualora \param{flags} contenga un valore
  non valido o \param{newfd} sia uguale a \param{oldfd}.
}  
\end{funcproto}

La funzione è identica a \func{dup2} ma prevede la possibilità di mantenere il
flag di \textit{close-on-exec} \itindex{close-on-exec} sul nuovo
file descriptor specificando \const{O\_CLOEXEC} in \param{flags} (che è l'unico
flag usabile in questo caso). Inoltre rileva esplicitamente la possibile
coincidenza fra \param{newfd} e \param{oldfd}, fallendo con un errore di
\errval{EINVAL}.


\subsection{Le funzioni di sincronizzazione dei dati}
\label{sec:file_sync}

Come accennato in sez.~\ref{sec:file_open_close} tutte le operazioni di
scrittura sono in genere bufferizzate dal kernel, che provvede ad effettuarle
in maniera asincrona, ad esempio accorpando gli accessi alla stessa zona del
disco, in un secondo tempo rispetto al momento della esecuzione della
\func{write}.

Per questo motivo quando è necessaria una sincronizzazione dei dati il sistema
mette a disposizione delle funzioni che provvedono a forzare lo scarico dei
dati dai buffer del kernel.  La prima di queste funzioni di sistema è
\funcd{sync}, il cui prototipo è:\footnote{questo è il prototipo usato a
  partire dalla \acr{glibc} 2.2.2 seguendo gli standard, in precedenza la
  funzione era definita come \code{int sync(void)} e ritornava sempre $0$.}

\begin{funcproto}{
\fhead{unistd.h}
\fdecl{void sync(void)}
\fdesc{Sincronizza il buffer della cache dei file col disco.} 
}

{La funzione non ritorna nulla e non prevede condizioni di errore.}  
\end{funcproto}

I vari standard prevedono che la funzione si limiti a far partire le
operazioni, ritornando immediatamente, con Linux fin dal kernel 1.3.20 invece
la funzione aspetta la conclusione delle operazioni di sincronizzazione. Si
tenga presente comunque che questo non dà la garanzia assoluta che i dati
siano integri dopo la chiamata, l'hardware dei dischi è in genere dotato di un
suo meccanismo interno di bufferizzazione che può ritardare ulteriormente la
scrittura effettiva.

La funzione viene usata dal comando \cmd{sync} quando si vuole forzare
esplicitamente lo scarico dei dati su disco, un tempo era invocata da un
apposito demone di sistema (in genere chiamato \cmd{update}) che eseguiva lo
scarico dei dati ad intervalli di tempo fissi.  Con le nuove versioni del
kernel queste operazioni vengono gestite direttamente dal sistema della
memoria virtuale, attraverso opportuni \textit{task} interni al kernel il cui
comportamento può essere controllato attraverso il file
\sysctlfile{vm/bdflush}.\footnote{per il significato dei valori che si possono
  scrivere in questo file si consulti la documentazione allegata ai sorgenti
  del kernel nel file \file{Documentation/sysctl/vm.txt}, trattandosi di
  argomenti di natura sistemistica non li prenderemo in esame.} Si tenga
presente che la funzione di sistema \funcm{bdflush}, che un tempo veniva usata
per queste impostazioni, è deprecata e causa semplicemente la stampa di un
messaggio nei log del kernel, pertanto non la prenderemo in esame.

Quando si vogliano scaricare i dati di un singolo file, ad esempio essere
sicuri che i dati di un database siano stati registrati su disco, si possono
usare le due funzioni di sistema \funcd{fsync} e \funcd{fdatasync}, i cui
prototipi sono:

\begin{funcproto}{
\fhead{unistd.h}
\fdecl{int fsync(int fd)}
\fdesc{Sincronizza dati e metadati di un file.} 
\fdecl{int fdatasync(int fd)}
\fdesc{Sincronizza i dati di un file.} 
}

{Le funzioni ritornano $0$ in caso di successo e $-1$ per un errore, nel qual
  caso \var{errno} assumerà uno dei valori: 
  \begin{errlist}
  \item[\errcode{EINVAL}] \param{fd} è un \index{file!speciali} file speciale
    che non supporta la sincronizzazione.
  \end{errlist}
  ed inoltre \errval{EBADF}, \errval{EIO} e \errval{EROFS} nel loro
  significato generico.}
\end{funcproto}

Entrambe le funzioni forzano la sincronizzazione col disco di tutti i dati del
file specificato, ed attendono fino alla conclusione delle operazioni. La
prima, \func{fsync} forza anche la sincronizzazione dei meta-dati del file,
che riguardano sia le modifiche alle tabelle di allocazione dei settori, che
gli altri dati contenuti \itindex{inode} nell'\textit{inode} che si leggono
con \func{fstat}, come i tempi del file. Se lo scopo dell'operazione, come
avviene spesso per i database, è assicurarsi che i dati raggiungano il disco e
siano rileggibili immediatamente in maniera corretta, è sufficiente l'uso di
\func{fdatasync} che non comporta anche l'esecuzione di operazioni non
necessarie all'integrità dei dati, come l'aggiornamento dei tempi di ultima
modifica ed ultimo accesso.

Si tenga presente che l'uso di queste funzioni non comporta la
sincronizzazione della directory che contiene il file e la scrittura della
relativa voce su disco, che se necessaria deve essere effettuata
esplicitamente con \func{fsync} sul file descriptor della
directory.\footnote{in realtà per il filesystem \acr{ext2}, quando lo si monta
  con l'opzione \cmd{sync}, il kernel provvede anche alla sincronizzazione
  automatica delle voci delle directory.}

L'uso di \func{sync} presenta in certi casi, quando ci sono più filesystem
montati, problemi di prestazioni dovute al fatto che la funzione provoca la
sincronizzazione dei dati su tutti quanti i filesystem, anche quando
interesserebbe che questo avvenga soltanto su quello dei file su cui si sta
lavorando, se i dati in attesa sono molti questo può causare seri problemi di
prestazioni. 

Per questo motivo è stata introdotta una nuova funzione di sistema,
\funcd{syncfs},\footnote{la funzione è stata introdotta a partire dal kernel
  2.6.39 ed è accessibile solo se è definita la macro \macro{\_GNU\_SOURCE}, è
  specifica di Linux e non prevista da nessuno standard.} che effettua lo
scarico dei dati soltanto per il filesystem su cui si sta operando, il suo
prototipo è:

\begin{funcproto}{
\fhead{unistd.h}
\fdecl{int syncfs(int fd)}
\fdesc{Sincronizza il buffer della cache dei file del singolo filesystem col
  disco.}
}

{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
  caso \var{errno} assumerà uno dei valori: 
  \begin{errlist}
    \item[\errcode{EBADF}] \param{fd} non è un descrittore valido.
  \end{errlist}
}  
\end{funcproto}

La funzione richiede che si specifichi nell'argomento \param{fd} un file
descriptor su cui si sta operando, e lo scarico dei dati sarà limitato al
filesystem su cui il file ad esso corrispondente si trova.


\subsection{Le \textit{at-functions}: \func{openat} e affini}
\label{sec:file_openat}

\itindbeg{at-functions}

Un problema generale che si pone con l'uso della funzione \func{open}, così
come per le altre funzioni che prendono come argomenti dei
\itindsub{pathname}{relativo} \textit{pathname} relativi, è la possibilità,
quando un \textit{pathname} relativo non fa riferimento ad un file posto
direttamente nella \index{directory~di~lavoro} directory di lavoro corrente,
che alcuni dei componenti del \textit{pathname} vengano modificati in
parallelo alla chiamata a \func{open}, cosa che lascia aperta la possibilità
di una \itindex{race~condition} \textit{race condition} in cui c'è spazio per
un \itindex{symlink~attack} \textit{symlink attack} (si ricordi quanto visto
per \func{access} in sez.~\ref{sec:file_perm_management}).

Inoltre come già accennato, la \index{directory~di~lavoro} directory di lavoro
corrente è una proprietà del singolo processo; questo significa che quando si
lavora con i \itindex{thread} \textit{thread} essa sarà la stessa per tutti,
ma esistono molti casi in cui sarebbe invece utile che ogni singolo
\itindex{thread} \textit{thread} avesse la sua \index{directory~di~lavoro}
directory di lavoro.

Per risolvere questi problemi, riprendendo una interfaccia già presente in
Solaris, a fianco delle normali funzioni che operano sui file (come
\func{open}, \func{mkdir}, ecc.) sono state introdotte delle ulteriori
funzioni, dette anche ``\textit{at-functions}'' in quanto contraddistinte dal
suffisso \texttt{at}, che permettono l'apertura di un file (o le rispettive
altre operazioni) usando un \itindsub{pathname}{relativo} \textit{pathname}
relativo ad una directory specificata.\footnote{l'introduzione è avvenuta su
  proposta dello sviluppatore principale della \acr{glibc} Urlich Drepper e le
  corrispondenti \textit{system call} sono state inserite nel kernel a partire
  dalla versione 2.6.16, in precedenza era disponibile una emulazione che, sia
  pure con prestazioni inferiori, funzionava facendo ricorso all'uso del
  filesystem \textit{proc} con l'apertura del file attraverso il riferimento a
  \textit{pathname} del tipo di \texttt{/proc/self/fd/dirfd/relative\_path}.}
Benché queste funzioni non siano presenti negli standard tradizionali esse
sono state adottate da altri sistemi unix-like come Solaris, i vari BSD, fino ad
essere incluse in una recente revisione (la POSIX.1-2008) dello standard
POSIX.1. Con la \acr{glibc} per l'accesso a queste funzioni è necessario
definire la macro \macro{\_ATFILE\_SOURCE}.

L'uso di queste funzioni prevede una apertura iniziale della directory che
sarà la base della risoluzione dei \itindsub{pathname}{relativo}
\textit{pathname} relativi che verranno usati in seguito, dopo di che si dovrà
passare il relativo file descriptor alle varie funzioni che useranno quella
directory come punto di partenza per la risoluzione. In questo modo, anche
quando si lavora con i \itindex{thread} \textit{thread}, si può mantenere una
\index{directory~di~lavoro} directory di lavoro diversa per ciascuno di essi.

Questo metodo, oltre a risolvere i problemi di \itindex{race~condition}
\textit{race condition}, consente anche di ottenere aumenti di prestazioni
significativi quando si devono eseguire molte operazioni su sezioni
dell'albero dei file che prevedono delle gerarchie di sottodirectory molto
profonde. Infatti in questo caso basta eseguire la risoluzione del
\textit{pathname} della directory di partenza una sola volta (nell'apertura
iniziale) e non tutte le volte che si deve accedere a ciascun file che essa
contiene.

La sintassi generale di queste nuove funzioni è che esse prevedono come primo
argomento il file descriptor della directory da usare come base per la
risoluzione dei nomi, mentre gli argomenti successivi restano identici a
quelli della corrispondente funzione ordinaria. Se ad esempio prendiamo in
esame la nuova funzione di sistema \funcd{openat}, avremo il prototipo:

\begin{funcproto}{
\fhead{fcntl.h}
\fdecl{int openat(int dirfd, const char *pathname, int flags)}
\fdecl{int openat(int dirfd, const char *pathname, int flags, mode\_t mode)}
\fdesc{Apre un file a partire da una directory di \index{directory~di~lavoro}
  lavoro.} 
}

{La funzione ritorna gli stessi valori e gli stessi codici di errore di
  \func{open}, ed in più:
  \begin{errlist}
  \item[\errcode{EBADF}] \param{dirfd} non è un file descriptor valido.
  \item[\errcode{ENOTDIR}] \param{pathname} è un \itindsub{pathname}{relativo}
    \textit{pathname} relativo, ma \param{dirfd} fa riferimento ad un file.
   \end{errlist}
}  
\end{funcproto}

Il comportamento delle nuove funzioni è del tutto analogo a quello delle
corrispettive classiche, con la sola eccezione del fatto che se fra i loro
argomenti si utilizza un \itindsub{pathname}{relativo} \textit{pathname}
relativo questo sarà risolto rispetto alla directory indicata
da \param{dirfd}. Qualora invece si usi un \itindsub{pathname}{assoluto}
\textit{pathname} assoluto \param{dirfd} verrà semplicemente ignorato. Infine
se per \param{dirfd} si usa il valore speciale \const{AT\_FDCWD}, la
risoluzione sarà effettuata rispetto alla directory di
\index{directory~di~lavoro} lavoro corrente del processo. Si tenga presente
però che questa, come le altre costanti \texttt{AT\_*}, è definita in
\headfile{fcntl.h}, pertanto se la si vuole usare occorrerà includere comunque
questo file, anche per le funzioni che non sono definite in esso.

Così come il comportamento, anche i valori di ritorno e le condizioni di
errore delle nuove funzioni sono gli stessi delle funzioni classiche, agli
errori si aggiungono però quelli dovuti a valori errati per \param{dirfd}; in
particolare si avrà un errore di \errcode{EBADF} se esso non è un file
descriptor valido, ed un errore di \errcode{ENOTDIR} se esso non fa
riferimento ad una directory, tranne il caso in cui si sia specificato un
\itindsub{pathname}{assoluto} \textit{pathname} assoluto, nel qual caso, come
detto, il valore di \param{dirfd} sarà completamente ignorato.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|c|l|}
    \hline
    \textbf{Funzione} &\textbf{Flags} &\textbf{Corrispondente} \\
    \hline
    \hline
     \func{faccessat} &$\bullet$&\func{access}  \\
     \funcm{fchmodat} &$\bullet$&\func{chmod}   \\
     \func{fchownat}  &$\bullet$&\func{chown},\func{lchown}\\
     \funcm{fstatat}  &$\bullet$&\func{stat},\func{lstat}  \\
     \func{utimensat} &$\bullet$&\func{utimes},\func{lutimes}\\
     \func{linkat}    &$\bullet$\footnotemark&\func{link}    \\
     \funcm{mkdirat}  & --      &\func{mkdir}   \\
     \funcm{mknodat}  & --      &\func{mknod}   \\
     \func{openat}    & --      &\func{open}    \\
     \funcm{readlinkat}& --     &\func{readlink}\\
     \funcm{renameat} & --      &\func{rename}  \\
     \funcm{symlinkat}& --      &\func{symlink} \\
     \func{unlinkat}  &$\bullet$&\func{unlink},\func{rmdir}  \\
     \funcm{mkfifoat} & --      &\func{mkfifo}  \\
    \hline
  \end{tabular}
  \caption{Corrispondenze fra le nuove funzioni ``\textit{at}'' e le
    corrispettive funzioni classiche.}
  \label{tab:file_atfunc_corr}
\end{table}

\footnotetext{in questo caso l'argomento \param{flags} è disponibile ed
  utilizzabile solo a partire dal kernel 2.6.18.}

In tab.~\ref{tab:file_atfunc_corr} si sono riportate le funzioni introdotte
con questa nuova interfaccia, con a fianco la corrispondente funzione
classica. La gran parte di queste seguono la convenzione appena vista per
\func{openat}, in cui agli argomenti della corrispondente funzione classica
viene anteposto l'argomento \param{dirfd}, ed hanno per il resto un
comportamento identico e non staremo pertanto a trattarle una per una. Per una
parte di queste, indicate dal contenuto della omonima colonna di
tab.~\ref{tab:file_atfunc_corr}, oltre al nuovo argomento iniziale, è prevista
anche l'aggiunta di un ulteriore argomento finale, \param{flags}.


% TODO manca prototipo di linkat, verificare se metterlo o metter menzione
% altre modifiche al riguardo nel 3.11 (AT_EMPTY_PATH?) vedi
% http://lwn.net/Articles/562488/ 
% TODO manca prototipo di utimensat, verificare se metterlo o metter menzione

Per tutte le funzioni che lo prevedono, a parte \func{unlinkat} e
\funcd{faccessat}, l'ulteriore argomento è stato introdotto solo per fornire
un meccanismo con cui modificarne il comportamento nel caso si stia operando
su un collegamento simbolico, così da poter scegliere se far agire la funzione
direttamente sullo stesso o sul file da esso referenziato. Dato che in certi
casi esso può fornire ulteriori indicazioni per modificare il comportamento
delle funzioni, \param{flags} deve comunque essere passato come maschera
binaria, ed impostato usando i valori delle appropriate costanti
\texttt{AT\_*}, definite in \headfile{fcntl.h}.

Come esempio di questo secondo tipo di funzioni possiamo considerare
\funcd{fchownat}, che può essere usata per sostituire sia \func{chown}
che \func{lchown}; il suo prototipo è:

\begin{funcproto}{
\fhead{unistd.h}
\fhead{fcntl.h} 
\fdecl{int fchownat(int dirfd, const char *pathname, uid\_t owner, gid\_t
    group, int flags)}
\fdesc{Modifica il proprietario di un file.} 
}

{La funzione ritorna gli stessi valori e gli stessi codici di errore di
  \func{chown}, ed in più:
  \begin{errlist}
  \item[\errcode{EBADF}] \param{dirfd} non è un file descriptor valido.
  \item[\errcode{EINVAL}] \param{flags} non ha un valore valido.
  \item[\errcode{ENOTDIR}] \param{pathname} è un \itindsub{pathname}{relativo}
    \textit{pathname} relativo, ma \param{dirfd} fa riferimento ad un file. 
  \end{errlist}
}  
\end{funcproto}

In questo caso il valore di \param{flags} stabilisce il comportamento della
funzione quando la si applica ad un collegamento simbolico, e l'unico valore
utilizzabile è \const{AT\_SYMLINK\_NOFOLLOW}, che se impostato indica alla
funzione di non eseguire la dereferenziazione di un eventuale collegamento
simbolico, facendo comportare \func{fchownat} come \func{lchown} invece che
come \func{chown}.

Come accennato fra tutte quelle marcate in tab.~\ref{tab:file_atfunc_corr}
solo due funzioni possono usare l'argomento \param{flags} per indicare altro
rispetto alla possibilità di seguire o meno un collegamento simbolico, la
prima di queste è \funcd{faccessat}, ed il suo prototipo è:

\begin{funcproto}{
\fhead{unistd.h}
\fdecl{int faccessat(int dirfd, const char *path, int mode, int flags)}
\fdesc{Controlla i permessi di accesso.} 
}

{La funzione ritorna gli stessi valori e gli stessi codici di errore di
  \func{access}, ed in più:
  \begin{errlist}
  \item[\errcode{EBADF}] \param{dirfd} non è un file descriptor valido.
  \item[\errcode{EINVAL}] \param{flags} non ha un valore valido.
  \item[\errcode{ENOTDIR}] \param{pathname} è un \itindsub{pathname}{relativo}
    \textit{pathname} relativo, ma \param{dirfd} fa riferimento ad un file. 
  \end{errlist}
}  
\end{funcproto}

La funzione esegue il controllo di accesso ad un file, ma
l'argomento \param{flags} consente di modificarne il comportamento rispetto a
quello ordinario di \func{access}. In questo caso esso può essere specificato
come maschera binaria di due valori: il solito \const{AT\_SYMLINK\_NOFOLLOW},
con il significato già spiegato, e \const{AT\_EACCES} per indicare alla
funzione di eseguire il controllo dei permessi usando l'\ids{UID} effettivo
invece di quello reale (il comportamento di default, che riprende quello di
\func{access}).


La seconda eccezione è \funcd{unlinkat}, in questo caso
l'argomento \param{flags} viene utilizzato perché tramite esso si può indicare
alla funzione di comportarsi sia come analogo di \func{unlink} che di
\func{rmdir}; il suo prototipo è:

\begin{funcproto}{
\fhead{fcntl.h}
\fdecl{int unlinkat(int dirfd, const char *pathname, int flags)}
\fdesc{Rimuove una voce da una directory.} 
}

{La funzione ritorna gli stessi valori e gli stessi codici di errore di
  \func{unlink} o di \func{rmdir} a seconda del valore di \param{flags}, ed in
  più:
  \begin{errlist}
  \item[\errcode{EBADF}] \param{dirfd} non è un file descriptor valido.
  \item[\errcode{EINVAL}] \param{flags} non ha un valore valido.
  \item[\errcode{ENOTDIR}] \param{pathname} è un \itindsub{pathname}{relativo}
    \textit{pathname} relativo, ma \param{dirfd} fa riferimento ad un file.
  \end{errlist}
}  
\end{funcproto}

Di default il comportamento di \func{unlinkat} è equivalente a quello che
avrebbe \func{unlink} applicata a \param{pathname}, fallendo in tutti i casi
in cui questo è una directory, se però si imposta \param{flags} al valore di
\const{AT\_REMOVEDIR}, essa si comporterà come \func{rmdir}, in tal
caso \param{pathname} deve essere una directory, che sarà rimossa qualora
risulti vuota.  Non essendo in questo caso prevista la possibilità di usare
altri valori (la funzione non segue comunque i collegamenti simbolici) anche
se \param{flags} è una maschera binaria, essendo \const{AT\_REMOVEDIR} l'unico
flag disponibile per questa funzione, lo si può assegnare direttamente.

Infine una terza funzione, \funcm{linkat}, utilizza in maniera diversa dalle
altre l'argomento \param{flags}, anche se in questo caso l'utilizzo continua
ad essere attinente al comportamento con i collegamenti simbolici. Si ricordi
che su Linux il comportamento di \func{link} è quello di non seguire mai i
collegamenti simbolici, pertanto l'uso ordinario dell'argomento parrebbe in
questo caso essere inutile.  A partire dal kernel 2.6.18 invece però è stato
aggiunta per questa funzione la possibilità di usare il valore
\const{AT\_SYMLINK\_FOLLOW}, che richiede di dereferenziare i collegamenti
simbolici.

Dato che questo è il comportamento adottato per un valore nullo
di \param{flags} da tutte le altre funzioni, \func{linkat} è l'unica per cui
può essere usato esplicitamente questo valore e per la quale non ha senso
usare \const{AT\_SYMLINK\_NOFOLLOW}. Per avere un quadro d'insieme si è
riassunto in tab.~\ref{tab:at-functions_constant_values} l'elenco delle
costanti utilizzabili per i valori di \param{flags}.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Costante} & \textbf{Significato} \\
    \hline
    \hline
    \const{AT\_SYMLINK\_NOFOLLOW}& Se impostato la funzione non esegue la
                                 dereferenziazione dei collegamenti simbolici.\\
    \const{AT\_SYMLINK\_FOLLOW}& Se impostato la funzione esegue la
                                 dereferenziazione dei collegamenti simbolici
                                 (usato esplicitamente solo da \func{linkat}).\\
    \const{AT\_EACCES}         & Usato solo da \func{faccessat}, richiede che
                                 il controllo dei permessi sia fatto usando
                                 l'\ids{UID} effettivo invece di quello
                                 reale.\\
    \const{AT\_REMOVEDIR}      & Usato solo da \func{unlinkat}, richiede che
                                 la funzione si comporti come \func{rmdir}
                                 invece che come \func{unlink}.\\
    \hline
  \end{tabular}  
  \caption{Le costanti utilizzate per i bit dell'argomento
    aggiuntivo \param{flags} delle \textit{at-functions}.} 
  \label{tab:at-functions_constant_values}
\end{table}


Un'ultima differenza fra le \textit{at-functions} e le funzioni tradizionali
di cui sono estensione è, come accennato in sez.~\ref{sec:file_temp_file},
quella relativa a \funcm{utimensat} che non è propriamente una corrispondente
esatta di \func{utimes} e \func{lutimes}, dato che questa funzione ha una
maggiore precisione nella indicazione dei tempi dei file, per i quali come per
\func{futimes}, si devono usare strutture \struct{timespec} che consentono una
precisione fino al nanosecondo.

% NOTA: manca prototipo di utimensat, per ora si lascia una menzione

\itindend{at-functions}

% TODO: manca prototipo e motivazione di fexecve, da trattare qui in quanto
% inserita nello stesso standard e da usare con openat, vedi 
% http://pubs.opengroup.org/onlinepubs/9699939699/toc.pdf


\subsection{Le operazioni di controllo}
\label{sec:file_fcntl_ioctl}

Oltre alle operazioni base esaminate in sez.~\ref{sec:file_unix_interface}
esistono tutta una serie di operazioni ausiliarie che è possibile eseguire su
un file descriptor, che non riguardano la normale lettura e scrittura di dati,
ma la gestione sia delle loro proprietà, che di tutta una serie di ulteriori
funzionalità che il kernel può mettere a disposizione.

Per le operazioni di manipolazione e di controllo delle varie proprietà e
caratteristiche di un file descriptor, viene usata la funzione di sistema
\funcd{fcntl},\footnote{ad esempio si gestiscono con questa funzione varie
  modalità di I/O asincrono (vedi sez.~\ref{sec:file_asyncronous_operation}) e
  il \itindex{file~locking} \textit{file locking} (vedi
  sez.~\ref{sec:file_locking}).} il cui prototipo è:

\begin{funcproto}{
\fhead{unistd.h}
\fhead{fcntl.h}
\fdecl{int fcntl(int fd, int cmd)}
\fdecl{int fcntl(int fd, int cmd, long arg)}
\fdecl{int fcntl(int fd, int cmd, struct flock * lock)}
\fdecl{int fcntl(int fd, int cmd, struct f\_owner\_ex * owner)}
\fdesc{Esegue una operazione di controllo sul file.} 
}

{La funzione ha valori di ritorno diversi a seconda dell'operazione richiesta
  in caso di successo mentre ritorna sempre $-1$ per un errore, nel qual caso
  \var{errno} assumerà valori diversi che dipendono dal tipo di operazione,
  l'unico valido in generale è:
  \begin{errlist}
  \item[\errcode{EBADF}] \param{fd} non è un file aperto.
  \end{errlist}
}  
\end{funcproto}

Il primo argomento della funzione è sempre il numero di file descriptor
\var{fd} su cui si vuole operare. Il comportamento di questa funzione, il
numero e il tipo degli argomenti, il valore di ritorno e gli eventuali errori
aggiuntivi, sono determinati dal valore dell'argomento \param{cmd} che in
sostanza corrisponde all'esecuzione di un determinato \textsl{comando}. A
seconda del comando specificato il terzo argomento può essere assente (ma se
specificato verrà ignorato), può assumere un valore intero di tipo
\ctyp{long}, o essere un puntatore ad una struttura \struct{flock}.

In sez.~\ref{sec:file_dup} abbiamo incontrato un esempio dell'uso di
\func{fcntl} per la duplicazione dei file descriptor, una lista di tutti i
possibili valori per \var{cmd}, e del relativo significato, dei codici di
errore restituiti e del tipo del terzo argomento (cui faremo riferimento con
il nome indicato nel precedente prototipo), è riportata di seguito:
\begin{basedescript}{\desclabelwidth{1.8cm}}
\item[\const{F\_DUPFD}] trova il primo file descriptor disponibile di valore
  maggiore o uguale ad \param{arg}, e ne fa un duplicato
  di \param{fd}, ritorna il nuovo file descriptor in caso di successo e $-1$
  in caso di errore. Oltre a \errval{EBADF} gli errori possibili sono
  \errcode{EINVAL} se \param{arg} è negativo o maggiore del massimo consentito
  o \errcode{EMFILE} se il processo ha già raggiunto il massimo numero di
  descrittori consentito.

\item[\const{F\_DUPFD\_CLOEXEC}] ha lo stesso effetto di \const{F\_DUPFD}, ma
  in più attiva il flag di \itindex{close-on-exec} \textit{close-on-exec} sul
  file descriptor duplicato, in modo da evitare una successiva chiamata con
  \const{F\_SETFD}. La funzionalità è stata introdotta con il kernel 2.6.24 ed
  è prevista nello standard POSIX.1-2008 (si deve perciò definire
  \macro{\_POSIX\_C\_SOURCE} ad un valore adeguato secondo quanto visto in
  sez.~\ref{sec:intro_gcc_glibc_std}).

\item[\const{F\_GETFD}] restituisce il valore dei \textit{file descriptor
    flags} di \param{fd} in caso di successo o $-1$ in caso di errore, il
  terzo argomento viene ignorato. Non sono previsti errori diversi da
  \errval{EBADF}. Al momento l'unico flag usato è quello di
  \itindex{close-on-exec} \textit{close-on-exec}, identificato dalla costante
  \const{FD\_CLOEXEC}, che serve a richiedere che il file venga chiuso nella
  esecuzione di una \func{exec} (vedi sez.~\ref{sec:proc_exec}). Un valore
  nullo significa pertanto che il flag non è impostato.

\item[\const{F\_SETFD}] imposta il valore dei \textit{file descriptor flags}
  al valore specificato con \param{arg}, ritorna un valore nullo in caso di
  successo e $-1$ in caso di errore. Non sono previsti errori diversi da
  \errval{EBADF}. Dato che l'unico flag attualmente usato è quello di
  \itindex{close-on-exec} \textit{close-on-exec}, identificato dalla costante
  \const{FD\_CLOEXEC}, tutti gli altri bit di \param{arg}, anche se impostati,
  vengono ignorati.\footnote{questo almeno è quanto avviene fino al kernel
    3.2, come si può evincere dal codice della funzione \texttt{do\_fcntl} nel
    file \texttt{fs/fcntl.c} dei sorgenti del kernel.}

\item[\const{F\_GETFL}] ritorna il valore dei \textit{file status flags} di
  \param{fd} in caso di successo o $-1$ in caso di errore, il terzo argomento
  viene ignorato. Non sono previsti errori diversi da \errval{EBADF}. Il
  comando permette di rileggere il valore di quei bit
  dell'argomento \param{flags} di \func{open} che vengono memorizzati nella
  relativa voce della \textit{file table} all'apertura del file, vale a dire
  quelli riportati in tab.~\ref{tab:open_access_mode_flag} e
  tab.~\ref{tab:open_operation_flag}). Si ricordi che quando si usa la
  funzione per determinare le modalità di accesso con cui è stato aperto il
  file è necessario estrarre i bit corrispondenti nel \textit{file status
    flag} con la maschera \const{O\_ACCMODE} come già accennato in
  sez.~\ref{sec:file_open_close}. 

\item[\const{F\_SETFL}] imposta il valore dei \textit{file status flags} al
  valore specificato da \param{arg}, ritorna un valore nullo in caso di
  successo o $-1$ in caso di errore. In generale possono essere impostati solo
  i flag riportati in tab.~\ref{tab:open_operation_flag}, su Linux si possono
  modificare soltanto \const{O\_APPEND}, \const{O\_ASYNC}, \const{O\_DIRECT},
  \const{O\_NOATIME} e \const{O\_NONBLOCK}. Oltre a \errval{EBADF} si otterrà
  \errcode{EPERM} se si cerca di rimuovere \const{O\_APPEND} da un file
  marcato come \textit{append-only} o se di cerca di impostare
  \const{O\_NOATIME} su un file di cui non si è proprietari (e non si hanno i
  permessi di amministratore) ed \errcode{EINVAL} se si cerca di impostare
  \const{O\_DIRECT} su un file che non supporta questo tipo di operazioni.

\item[\const{F\_GETLK}] richiede un controllo sul file lock specificato da
  \param{lock}, sovrascrivendo la struttura da esso puntata con il risultato,
  ritorna un valore nullo in caso di successo o $-1$ in caso di errore. Come
  per i due successivi comandi oltre a \errval{EBADF} se \param{lock} non è un
  puntatore valido restituisce l'errore generico \errcode{EFAULT}. Questa
  funzionalità è trattata in dettaglio in sez.~\ref{sec:file_posix_lock}.

\item[\const{F\_SETLK}] richiede o rilascia un file lock a seconda di quanto
  specificato nella struttura puntata da \param{lock}, ritorna un valore nullo
  in caso di successo e $-1$ se il file lock è tenuto da qualcun altro, nel
  qual caso si ha un errore di \errcode{EACCES} o \errcode{EAGAIN}.  Questa
  funzionalità è trattata in dettaglio in sez.~\ref{sec:file_posix_lock}.

\item[\const{F\_SETLKW}] identica a \const{F\_SETLK} eccetto per il fatto che
  la funzione non ritorna subito ma attende che il blocco sia rilasciato, se
  l'attesa viene interrotta da un segnale la funzione restituisce $-1$ e
  imposta \var{errno} a \errcode{EINTR}.  Questa funzionalità è trattata in
  dettaglio in sez.~\ref{sec:file_posix_lock}.

\item[\const{F\_GETOWN}] restituisce in caso di successo l'identificatore del
  processo o del \itindex{process~group} \textit{process group} (vedi
  sez.~\ref{sec:sess_proc_group}) che è preposto alla ricezione del segnale
  \signal{SIGIO} (o l'eventuale segnale alternativo impostato con
  \const{F\_SETSIG}) per gli eventi asincroni associati al file
  descriptor \param{fd} e del segnale \signal{SIGURG} per la notifica dei dati
  urgenti di un socket (vedi sez.~\ref{sec:TCP_urgent_data}). Restituisce $-1$
  in caso di errore ed il terzo argomento viene ignorato. Non sono previsti
  errori diversi da \errval{EBADF}.

  Per distinguerlo dal caso in cui il segnale viene inviato a un singolo
  processo, nel caso di un \textit{process group} viene restituito un valore
  negativo il cui valore assoluto corrisponde all'identificatore del
  \itindex{process~group} \textit{process group}. Con Linux questo comporta un
  problema perché se il valore restituito dalla \textit{system call} è
  compreso nell'intervallo fra $-1$ e $-4095$ in alcune architetture questo
  viene trattato dalla \acr{glibc} come un errore,\footnote{il problema deriva
    dalle limitazioni presenti in architetture come quella dei normali PC
    (i386) per via delle modalità in cui viene effettuata l'invocazione delle
    \textit{system call} che non consentono di restituire un adeguato codice
    di ritorno.} per cui in tal caso \func{fcntl} ritornerà comunque $-1$
  mentre il valore restituito dalla \textit{system call} verrà assegnato ad
  \var{errno}, cambiato di segno.

  Per questo motivo con il kernel 2.6.32 è stato introdotto il comando
  alternativo \const{F\_GETOWN\_EX}, che vedremo a breve, che consente di
  evitare il problema. A partire dalla versione 2.11 la \acr{glibc}, se
  disponibile, usa questa versione alternativa per mascherare il problema
  precedente e restituire un valore corretto in tutti i casi.\footnote{in cui
    cioè viene restituito un valore negativo corretto qualunque sia
    l'identificatore del \itindex{process~group} \textit{process group}, che
    non potendo avere valore unitario (non esiste infatti un
    \itindex{process~group} \textit{process group} per \cmd{init}) non può
    generare ambiguità con il codice di errore.} Questo però comporta che il
  comportamento del comando può risultare diverso a seconda delle versioni
  della \acr{glibc} e del kernel.

\item[\const{F\_SETOWN}] imposta, con il valore dell'argomento \param{arg},
  l'identificatore del processo o del \itindex{process~group} \textit{process
    group} che riceverà i segnali \signal{SIGIO} e \signal{SIGURG} per gli
  eventi associati al file descriptor \param{fd}. Ritorna un valore nullo in
  caso di successo o $-1$ in caso di errore. Oltre a \errval{EBADF} gli errori
  possibili sono \errcode{ESRCH} se \param{arg} indica un processo o un
  \itindex{process~group} \textit{process group} inesistente.

  L'impostazione è soggetta alle stesse restrizioni presenti sulla funzione
  \func{kill} (vedi sez.~\ref{sec:sig_kill_raise}), per cui un utente non
  privilegiato può inviare i segnali solo ad un processo che gli appartiene,
  in genere comunque si usa il processo corrente.  Come per \const{F\_GETOWN},
  per indicare un \itindex{process~group} \textit{process group} si deve usare
  per \param{arg} un valore negativo, il cui valore assoluto corrisponda
  all'identificatore del \itindex{process~group} \textit{process group}.

  A partire dal kernel 2.6.12 se si sta operando con i \textit{thread} della
  implementazione nativa di Linux (quella della NTPL, vedi
  sez.~\ref{sec:linux_ntpl}) e se si è impostato un segnale specifico con
  \const{F\_SETSIG}, un valore positivo di \param{arg} viene interpretato come
  indicante un \textit{Thread ID} e non un \textit{Process ID}.  Questo
  consente di inviare il segnale impostato con \const{F\_SETSIG} ad uno
  specifico \textit{thread}. In genere questo non comporta differenze
  significative per il processi ordinari, in cui non esistono altri
  \textit{thread}, dato che su Linux il \textit{thread} principale, che in tal
  caso è anche l'unico, mantiene un valore del \textit{Thread ID} uguale al
  \ids{PID} del processo. Il problema è però che questo comportamento non si
  applica a \signal{SIGURG}, per il quale \param{arg} viene sempre
  interpretato come l'identificatore di un processo o di un
  \itindex{process~group} \textit{process group}.

\item[\const{F\_GETOWN\_EX}] legge nella struttura puntata
  dall'argomento \param{owner} l'identificatore del processo, \textit{thread} o
  \itindex{process~group} \textit{process group} (vedi
  sez.~\ref{sec:sess_proc_group}) che è preposto alla ricezione dei segnali
  \signal{SIGIO} e \signal{SIGURG} per gli eventi associati al file
  descriptor \param{fd}.  Ritorna un valore nullo in caso di successo o $-1$
  in caso di errore. Oltre a  \errval{EBADF} e da
  \errval{EFAULT} se \param{owner} non è un puntatore valido.  

  Il comando, che è disponibile solo a partire dal kernel 2.6.32, effettua lo
  stesso compito di \const{F\_GETOWN} di cui costituisce una evoluzione che
  consente di superare i limiti e le ambiguità relative ai valori restituiti
  come identificativo. A partire dalla versione 2.11 della \acr{glibc} esso
  viene usato dalla libreria per realizzare una versione di \func{fcntl} che
  non presenti i problemi illustrati in precedenza per la versione precedente
  di \const{F\_GETOWN}.  Il comando è specifico di Linux ed utilizzabile solo
  se si è definita la macro \macro{\_GNU\_SOURCE}.

\item[\const{F\_SETOWN\_EX}] imposta con il valore della struttura
  \struct{f\_owner\_ex} puntata \param{owner}, l'identificatore del processo o
  del \itindex{process~group} \textit{process group} che riceverà i segnali
  \signal{SIGIO} e \signal{SIGURG} per gli eventi associati al file
  descriptor \param{fd}. Ritorna un valore nullo in caso di successo o $-1$ in
  caso di errore, con gli stessi errori di \const{F\_SETOWN} più
  \errcode{EINVAL} se il campo \var{type} di \struct{f\_owner\_ex} non indica
  un tipo di identificatore valido.

  \begin{figure}[!htb]
    \footnotesize \centering
    \begin{varwidth}[c]{0.5\textwidth}
      \includestruct{listati/f_owner_ex.h}
    \end{varwidth}
    \normalsize 
    \caption{La struttura \structd{f\_owner\_ex}.} 
    \label{fig:f_owner_ex}
  \end{figure}

  Come \const{F\_GETOWN\_EX} il comando richiede come terzo argomento il
  puntatore ad una struttura \struct{f\_owner\_ex} la cui definizione è
  riportata in fig.~\ref{fig:f_owner_ex}, in cui il primo campo indica il tipo
  di identificatore il cui valore è specificato nel secondo campo, che assume
  lo stesso significato di \param{arg} per \const{F\_SETOWN}. Per il campo
  \var{type} i soli valori validi sono \const{F\_OWNER\_TID},
  \const{F\_OWNER\_PID} e \const{F\_OWNER\_PGRP}, che indicano rispettivamente
  che si intende specificare con \var{pid} un \textit{Tread ID}, un
  \textit{Process ID} o un \textit{Process Group ID}. A differenza di
  \const{F\_SETOWN} se si specifica un \textit{Tread ID} questo riceverà sia
  \signal{SIGIO} (o il segnale impostato con \const{F\_SETSIG}) che
  \signal{SIGURG}. Il comando è specifico di Linux, è disponibile solo a
  partire dal kernel 2.6.32, ed è utilizzabile solo se si è definita la macro
  \macro{\_GNU\_SOURCE}.

\item[\const{F\_GETSIG}] restituisce il valore del segnale inviato dai vari
  meccanismi di I/O asincrono associati al file descriptor \param{fd} (quelli
  trattati in sez.~\ref{sec:file_asyncronous_operation}) in caso di successo o
  $-1$ in caso di errore, il terzo argomento viene ignorato. Non sono previsti
  errori diversi da \errval{EBADF}.  Un valore nullo indica che si sta usando
  il segnale predefinito, che è \signal{SIGIO}. Un valore diverso da zero
  indica il segnale che è stato impostato con \const{F\_SETSIG}, che può
  essere anche lo stesso \signal{SIGIO}. Il comando è specifico di Linux ed
  utilizzabile solo se si è definita la macro \macro{\_GNU\_SOURCE}.

\item[\const{F\_SETSIG}] imposta il segnale inviato dai vari meccanismi di I/O
  asincrono associati al file descriptor \param{fd} (quelli trattati in
  sez.~\ref{sec:file_asyncronous_operation}) al valore indicato
  da \param{arg}, ritorna un valore nullo in caso di successo o $-1$ in caso
  di errore.  Oltre a \errval{EBADF} gli errori possibili sono
  \errcode{EINVAL} se \param{arg} indica un numero di segnale non valido.  Un
  valore nullo di \param{arg} indica di usare il segnale predefinito, cioè
  \signal{SIGIO}. Un valore diverso da zero, compreso lo stesso
  \signal{SIGIO}, specifica il segnale voluto.  Il comando è specifico di
  Linux ed utilizzabile solo se si è definita la macro \macro{\_GNU\_SOURCE}.

  L'impostazione di un valore diverso da zero permette inoltre, se si è
  installato il gestore del segnale come \var{sa\_sigaction} usando
  \const{SA\_SIGINFO}, (vedi sez.~\ref{sec:sig_sigaction}), di rendere
  disponibili al gestore informazioni ulteriori riguardo il file che ha
  generato il segnale attraverso i valori restituiti in
  \struct{siginfo\_t}. Se inoltre si imposta un segnale \textit{real-time} si
  potranno sfruttare le caratteristiche di avanzate di questi ultimi (vedi
  sez.~\ref{sec:sig_real_time}), ed in particolare la capacità di essere
  accumulati in una coda prima della notifica.

\item[\const{F\_GETLEASE}] restituisce il tipo di \itindex{file~lease}
  \textit{file lease} che il processo detiene nei confronti del file
  descriptor \var{fd} o $-1$ in caso di errore, il terzo argomento viene
  ignorato. Non sono previsti errori diversi da \errval{EBADF}.  Il comando è
  specifico di Linux ed utilizzabile solo se si è definita la macro
  \macro{\_GNU\_SOURCE}.  Questa funzionalità è trattata in dettaglio in
  sez.~\ref{sec:file_asyncronous_lease}.

\item[\const{F\_SETLEASE}] imposta o rimuove a seconda del valore
  di \param{arg} un \itindex{file~lease} \textit{file lease} sul file
  descriptor \var{fd} a seconda del valore indicato da \param{arg}. Ritorna un
  valore nullo in caso di successo o $-1$ in caso di errore. Oltre a
  \errval{EBADF} si otterrà \errcode{EINVAL} se si è specificato un valore non
  valido per \param{arg} (deve essere usato uno dei valori di
  tab.~\ref{tab:file_lease_fctnl}), \errcode{ENOMEM} se non c'è memoria
  sufficiente per creare il \textit{file lease}, \errcode{EACCES} se non si è
  il proprietario del file e non si hanno i privilegi di
  amministratore.\footnote{per la precisione occorre la capacità
    \itindex{capabilities} \const{CAP\_LEASE}.}

  Il supporto il supporto per i \textit{file lease}, che consente ad un
  processo che detiene un \textit{lease} su un file di riceve una notifica
  qualora un altro processo cerchi di eseguire una \func{open} o una
  \func{truncate} su di esso è stato introdotto a partire dai kernel della
  serie 2.4 Il comando è specifico di Linux ed utilizzabile solo se si è
  definita la macro \macro{\_GNU\_SOURCE}. Questa funzionalità è trattata in
  dettaglio in sez.~\ref{sec:file_asyncronous_lease}.

\item[\const{F\_NOTIFY}] attiva il meccanismo di notifica asincrona per cui
  viene riportato al processo chiamante, tramite il segnale \signal{SIGIO} (o
  altro segnale specificato con \const{F\_SETSIG}) ogni modifica eseguita o
  direttamente sulla directory cui \var{fd} fa riferimento, o su uno dei file
  in essa contenuti; ritorna un valore nullo in caso di successo o $-1$ in
  caso di errore. Il comando è specifico di Linux ed utilizzabile solo se si è
  definita la macro \macro{\_GNU\_SOURCE}.  Questa funzionalità, disponibile
  dai kernel della serie 2.4.x, è trattata in dettaglio in
  sez.~\ref{sec:file_asyncronous_lease}.

\item[\const{F\_GETPIPE\_SZ}] restituisce in caso di successo la dimensione
  del buffer associato alla \textit{pipe} \param{fd} (vedi
  sez.~\ref{sec:ipc_pipes}) o $-1$ in caso di errore, il terzo argomento viene
  ignorato. Non sono previsti errori diversi da \errval{EBADF}, che viene
  restituito anche se il file descriptor non è una pipe. Il comando è
  specifico di Linux, è disponibile solo a partire dal kernel 2.6.35, ed è
  utilizzabile solo se si è definita la macro \macro{\_GNU\_SOURCE}.

\item[\const{F\_SETPIPE\_SZ}] imposta la dimensione del buffer associato alla
  \textit{pipe} \param{fd} (vedi sez.~\ref{sec:ipc_unix}) ad un valore uguale
  o superiore a quello indicato dall'argomento \param{arg}. Ritorna un valore
  nullo in caso di successo o $-1$ in caso di errore. Oltre a \errval{EBADF}
  gli errori possibili sono \errcode{EBUSY} se si cerca di ridurre la
  dimensione del buffer al di sotto della quantità di dati effettivamente
  presenti su di esso ed \errcode{EPERM} se un processo non privilegiato cerca
  di impostare un valore troppo alto.  La dimensione minima del buffer è pari
  ad una pagina di memoria, a cui verrà comunque arrotondata ogni dimensione
  inferiore, il valore specificato viene in genere arrotondato per eccesso al
  valore ritenuto più opportuno dal sistema, pertanto una volta eseguita la
  modifica è opportuno rileggere la nuova dimensione con
  \const{F\_GETPIPE\_SZ}. I processi non privilegiati\footnote{{per la
      precisione occorre la capacità \itindex{capabilities}
      \const{CAP\_SYS\_RESOURCE}.}} non possono impostare un valore valore
  superiore a quello indicato da \sysctlfile{fs/pipe-size-max}.  Il comando è
  specifico di Linux, è disponibile solo a partire dal kernel 2.6.35, ed è
  utilizzabile solo se si è definita la macro \macro{\_GNU\_SOURCE}.

\end{basedescript}

La maggior parte delle funzionalità controllate dai comandi di \func{fcntl}
sono avanzate e richiedono degli approfondimenti ulteriori, saranno pertanto
riprese più avanti quando affronteremo le problematiche ad esse relative. In
particolare le tematiche relative all'I/O asincrono e ai vari meccanismi di
notifica saranno trattate in maniera esaustiva in
sez.~\ref{sec:file_asyncronous_operation} mentre quelle relative al
\itindex{file~locking} \textit{file locking} saranno esaminate in
sez.~\ref{sec:file_locking}). L'uso di questa funzione con i socket verrà
trattato in sez.~\ref{sec:sock_ctrl_func}.

La gran parte dei comandi di \func{fcntl} (\const{F\_DUPFD}, \const{F\_GETFD},
\const{F\_SETFD}, \const{F\_GETFL}, \const{F\_SETFL}, \const{F\_GETLK},
\const{F\_SETLK} e \const{F\_SETLKW}) sono previsti da SVr4 e 4.3BSD e
standardizzati in POSIX.1-2001 che inoltre prevede gli ulteriori
\const{F\_GETOWN} e \const{F\_SETOWN}. Pertanto nell'elenco si sono indicate
esplicitamente soltanto le ulteriori richieste in termini delle macro di
funzionalità di sez.~\ref{sec:intro_gcc_glibc_std} soltanto per le
funzionalità inserite in standard successivi o specifiche di Linux.


% \subsection{La funzione \func{ioctl}}
% \label{sec:file_ioctl}

Benché l'interfaccia di gestione dell'I/O sui file di cui abbiamo parlato
finora si sia dimostrata valida anche per l'interazione diretta con le
periferiche attraverso i loro file di dispositivo, consentendo di usare le
stesse funzioni utilizzate per i normali file di dati, esistono però
caratteristiche peculiari, specifiche dell'hardware e delle funzionalità che
ciascun dispositivo può provvedere, che non possono venire comprese in questa
interfaccia astratta come ad esempio l'impostazione della velocità di una
porta seriale, o le dimensioni di un framebuffer.

Per questo motivo nell'architettura del sistema è stata prevista l'esistenza
di una apposita funzione di sistema, \funcd{ioctl}, come meccanismo generico
per compiere operazioni specializzate; il suo prototipo è:

\begin{funcproto}{
\fhead{sys/ioctl.h}
\fdecl{int ioctl(int fd, int request, ...)}
\fdesc{Esegue una operazione speciale.} 
}

{La funzione ritorna $0$ in caso di successo nella maggior parte dei casi, ma
  alcune operazioni possono restituire un valore positivo, mentre ritorna
  sempre $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei
  valori:
  \begin{errlist}
  \item[\errcode{EINVAL}] gli argomenti \param{request} o \param{argp} non sono
    validi.
  \item[\errcode{ENOTTY}] il file \param{fd} non è associato con un
    dispositivo, o la richiesta non è applicabile all'oggetto a cui fa
    riferimento \param{fd}.
  \end{errlist}
  ed inoltre \errval{EBADF} e \errval{EFAULT} nel loro significato generico.}
\end{funcproto}


La funzione richiede che si passi come primo argomento un file
descriptor \param{fd} regolarmente aperto, mentre l'operazione da compiere
deve essere indicata dal valore dell'argomento \param{request}. Il terzo
argomento dipende dall'operazione prescelta; tradizionalmente è specificato
come \code{char * argp}, da intendersi come puntatore ad un area di memoria
generica (all'epoca della creazione di questa funzione infatti ancora non era
stato introdotto il tipo \ctyp{void}) ma per certe operazioni può essere
omesso, e per altre è un semplice intero.

Normalmente la funzione ritorna zero in caso di successo e $-1$ in caso di
errore, ma per alcune operazioni il valore di ritorno, che nel caso viene
impostato ad un valore positivo, può essere utilizzato come indicazione del
risultato della stessa. È più comune comunque restituire i risultati
all'indirizzo puntato dal terzo argomento.

Data la genericità dell'interfaccia non è possibile classificare in maniera
sistematica le operazioni che si possono gestire con \func{ioctl}, un breve
elenco di alcuni esempi di esse è il seguente:
\begin{itemize*}
\item il cambiamento dei font di un terminale.
\item l'esecuzione di una traccia audio di un CDROM.
\item i comandi di avanti veloce e di riavvolgimento di un nastro.
\item il comando di espulsione di un dispositivo rimovibile.
\item l'impostazione della velocità trasmissione di una linea seriale.
\item l'impostazione della frequenza e della durata dei suoni emessi dallo
  speaker.
\item l'impostazione degli attributi dei file su un filesystem
  ext2.\footnote{i comandi \texttt{lsattr} e \texttt{chattr} fanno questo con
    delle \func{ioctl} dedicate, usabili solo su questo filesystem e derivati
    successivi (come ext3).}
\end{itemize*}

In generale ogni dispositivo ha un suo insieme di operazioni specifiche
effettuabili attraverso \func{ioctl}, tutte queste sono definite nell'header
file \headfile{sys/ioctl.h}, e devono essere usate solo sui dispositivi cui
fanno riferimento. Infatti anche se in genere i valori di \param{request} sono
opportunamente differenziati a seconda del dispositivo\footnote{il kernel usa
  un apposito \textit{magic number} per distinguere ciascun dispositivo nella
  definizione delle macro da usare per \param{request}, in modo da essere
  sicuri che essi siano sempre diversi, ed il loro uso per dispositivi diversi
  causi al più un errore.  Si veda il capitolo quinto di \cite{LinDevDri} per
  una trattazione dettagliata dell'argomento.} così che la richiesta di
operazioni relative ad altri dispositivi usualmente provoca il ritorno della
funzione con una condizione di errore, in alcuni casi, relativi a valori
assegnati prima che questa differenziazione diventasse pratica corrente, si
potrebbero usare valori validi anche per il dispositivo corrente, con effetti
imprevedibili o indesiderati.

Data la assoluta specificità della funzione, il cui comportamento varia da
dispositivo a dispositivo, non è possibile fare altro che dare una descrizione
sommaria delle sue caratteristiche; torneremo ad esaminare in seguito quelle
relative ad alcuni casi specifici, ad esempio la gestione dei terminali è
effettuata attraverso \func{ioctl} in quasi tutte le implementazioni di Unix,
mentre per l'uso di \func{ioctl} con i socket si veda
sez.~\ref{sec:sock_ctrl_func}. 

Riportiamo qui solo l'elenco delle operazioni che sono predefinite per
qualunque file, caratterizzate dal prefisso \texttt{FIO}. Queste operazioni
sono definite nel kernel a livello generale, e vengono sempre interpretate per
prime, per cui, come illustrato in \cite{LinDevDri}, eventuali operazioni
specifiche che usino lo stesso valore verrebbero ignorate:
\begin{basedescript}{\desclabelwidth{2.0cm}}
\item[\const{FIOCLEX}] imposta il flag di \itindex{close-on-exec}
  \textit{close-on-exec} sul file, in questo caso, essendo usata come
  operazione logica, \func{ioctl} non richiede un terzo argomento, il cui
  eventuale valore viene ignorato.
\item[\const{FIONCLEX}] cancella il flag di \itindex{close-on-exec}
  \textit{close-on-exec} sul file, in questo caso, essendo usata come
  operazione logica, \func{ioctl} non richiede un terzo argomento, il cui
  eventuale valore viene ignorato.
\item[\const{FIOASYNC}] abilita o disabilita la modalità di I/O asincrono sul
  file (vedi sez.~\ref{sec:signal_driven_io}); il terzo argomento
  deve essere un puntatore ad un intero (cioè di tipo \texttt{const int *})
  che contiene un valore logico (un valore nullo disabilita, un valore non
  nullo abilita).
\item[\const{FIONBIO}] abilita o disabilita sul file l'I/O in modalità non
  bloccante; il terzo argomento deve essere un puntatore ad un intero (cioè di
  tipo \texttt{const int *}) che contiene un valore logico (un valore nullo
  disabilita, un valore non nullo abilita).
\item[\const{FIOSETOWN}] imposta il processo che riceverà i segnali
  \signal{SIGURG} e \signal{SIGIO} generati sul file; il terzo argomento deve
  essere un puntatore ad un intero (cioè di tipo \texttt{const int *}) il cui
  valore specifica il PID del processo.
\item[\const{FIOGETOWN}] legge il processo che riceverà i segnali
  \signal{SIGURG} e \signal{SIGIO} generati sul file; il terzo argomento deve
  essere un puntatore ad un intero (cioè di tipo \texttt{int *}) su cui sarà
  scritto il PID del processo.
\item[\const{FIONREAD}] legge il numero di byte disponibili in lettura sul
  file descriptor; questa operazione è disponibile solo su alcuni file
  descriptor, in particolare sui socket (vedi sez.~\ref{sec:sock_ioctl_IP}) o
  sui file descriptor di \textit{epoll} (vedi sez.~\ref{sec:file_epoll}), il
  terzo argomento deve essere un puntatore ad un intero (cioè di tipo
  \texttt{int *}) su cui sarà restituito il valore.
\item[\const{FIOQSIZE}] restituisce la dimensione corrente di un file o di una
  directory, mentre se applicata ad un dispositivo fallisce con un errore di
  \errcode{ENOTTY}; il terzo argomento deve essere un puntatore ad un intero
  (cioè di tipo \texttt{int *}) su cui sarà restituito il valore.
\end{basedescript}

% TODO aggiungere FIBMAP e FIEMAP, vedi http://lwn.net/Articles/260795/,
% http://lwn.net/Articles/429345/ 

Si noti però come la gran parte di queste operazioni specifiche dei file (per
essere precisi le prime sei dell'elenco) siano effettuabili in maniera
generica anche tramite l'uso di \func{fcntl}. Le due funzioni infatti sono
molto simili e la presenza di questa sovrapposizione è principalmente dovuta
al fatto che alle origini di Unix i progettisti considerarono che era
necessario trattare diversamente rispetto alle operazione di controllo delle
modalità di I/O file e dispositivi usando \func{fcntl} per i primi e
\func{ioctl} per i secondi, all'epoca tra l'altro i dispositivi che usavano
\func{ioctl} erano sostanzialmente solo i terminali, il che spiega l'uso
comune di \errcode{ENOTTY} come codice di errore. Oggi non è più così ma le
due funzioni sono rimaste.

% TODO trovare qualche posto per la eventuale documentazione delle seguenti
% (bassa/bassissima priorità)
% EXT4_IOC_MOVE_EXT (dal 2.6.31)


% \chapter{}

\section{L'interfaccia standard ANSI C}
\label{sec:files_std_interface}


Come visto in sez.~\ref{sec:file_unix_interface} le operazioni di I/O sui file
sono gestibili a basso livello con l'interfaccia standard unix, che ricorre
direttamente alle \textit{system call} messe a disposizione dal kernel.

Questa interfaccia però non provvede le funzionalità previste dallo standard
ANSI C, che invece sono realizzate attraverso opportune funzioni di libreria.
Queste funzioni di libreria, insieme alle altre funzioni definite dallo
standard (che sono state implementate la prima volta da Ritchie nel 1976 e da
allora sono rimaste sostanzialmente immutate), vengono a costituire il nucleo
delle \acr{glibc} per la gestione dei file.

Esamineremo in questa sezione le funzioni base dell'interfaccia degli
\textit{stream}, analoghe a quelle di sez.~\ref{sec:file_unix_interface} per i
file descriptor. In particolare vedremo come aprire, leggere, scrivere e
cambiare la posizione corrente in uno \textit{stream}.


\subsection{I \textit{file stream}}
\label{sec:file_stream}

\itindbeg{file~stream}

Come più volte ribadito, l'interfaccia dei file descriptor è un'interfaccia di
basso livello, che non provvede nessuna forma di formattazione dei dati e
nessuna forma di bufferizzazione per ottimizzare le operazioni di I/O.

In \cite{APUE} Stevens descrive una serie di test sull'influenza delle
dimensioni del blocco di dati (l'argomento \param{buf} di \func{read} e
\func{write}) nell'efficienza nelle operazioni di I/O con i file descriptor,
evidenziando come le prestazioni ottimali si ottengano a partire da dimensioni
del buffer dei dati pari a quelle dei blocchi del filesystem (il valore dato
dal campo \var{st\_blksize} di \struct{stat}), che di norma corrispondono alle
dimensioni dei settori fisici in cui è suddiviso il disco.

Se il programmatore non si cura di effettuare le operazioni in blocchi di
dimensioni adeguate, le prestazioni sono inferiori.  La caratteristica
principale dell'interfaccia degli \textit{stream} è che essa provvede da sola
alla 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
\textit{file stream}, dato che non è più necessario doversi preoccupare dei
dettagli con cui viene gestita la comunicazione con l'hardware sottostante
(come nel caso della dimensione dei blocchi del filesystem), ed un file può
essere sempre considerato come composto da un flusso continuo di dati, da cui
deriva appunto il nome \textit{stream}.

A parte i dettagli legati alla gestione delle operazioni di lettura e
scrittura, sia per quel che riguarda la bufferizzazione che le formattazioni,
per tutto il resto i \textit{file stream} restano del tutto equivalenti ai
file descriptor (sui quali sono basati), ed in particolare continua a valere
quanto visto in sez.~\ref{sec:file_shared_access} a proposito dell'accesso
concorrente ed in sez.~\ref{sec:file_access_control} per il controllo di
accesso.

\itindend{file~stream}

Per ragioni storiche la struttura di dati che rappresenta uno \textit{stream}
è stata chiamata \type{FILE}, questi oggetti sono creati dalle funzioni di
libreria e contengono tutte le informazioni necessarie a gestire le operazioni
sugli \textit{stream}, come la posizione corrente, lo stato del buffer e degli
indicatori di stato e di fine del file.

Per questo motivo gli utenti non devono mai utilizzare direttamente o allocare
queste strutture (che sono dei \index{tipo!opaco} \textsl{tipi opachi}) ma
usare sempre puntatori del tipo \texttt{FILE *} ottenuti dalla libreria
stessa, tanto che in certi casi il termine di puntatore a file è diventato
sinonimo di \textit{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 \headfile{stdio.h}.

Ai tre file descriptor standard (vedi tab.~\ref{tab:file_std_files}) aperti
per ogni processo, corrispondono altrettanti \textit{stream}, che
rappresentano i canali standard di input/output prestabiliti; anche questi tre
\textit{stream} sono identificabili attraverso dei nomi simbolici definiti
nell'header \headfile{stdio.h} che sono:

\begin{basedescript}{\desclabelwidth{3.0cm}}
\item[\var{FILE *stdin}] Lo \itindex{standard~input} \textit{standard input}
  cioè il \textit{file stream} da cui il processo riceve ordinariamente i dati
  in ingresso. Normalmente è associato dalla shell all'input del terminale e
  prende i caratteri dalla tastiera.
\item[\var{FILE *stdout}] Lo \itindex{standard~output} \textit{standard
    output} cioè il \textit{file stream} su cui il processo invia
  ordinariamente i dati in uscita. Normalmente è associato dalla shell
  all'output del terminale e scrive sullo schermo.
\item[\var{FILE *stderr}] Lo \textit{standard error} \textit{standard error}
  cioè il \textit{file 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}

Nella \acr{glibc} \var{stdin}, \var{stdout} e \var{stderr} sono effettivamente
tre variabili di tipo \type{FILE}\texttt{ *} che possono essere usate come
tutte le altre, ad esempio si può effettuare una redirezione dell'output di un
programma con il semplice codice: \includecodesnip{listati/redir_stdout.c} ma
in altri sistemi queste variabili possono essere definite da macro, e se si
hanno problemi di portabilità e si vuole essere sicuri, diventa opportuno
usare la funzione \func{freopen}.


\subsection{Le modalità di bufferizzazione}
\label{sec:file_buffering}

La bufferizzazione è una delle caratteristiche principali dell'interfaccia
degli \textit{stream}; lo scopo è quello di ridurre al minimo il numero di
\textit{system call} (\func{read} o \func{write}) eseguite nelle operazioni di
input/output. Questa funzionalità è assicurata automaticamente dalla libreria,
ma costituisce anche uno degli aspetti più comunemente fraintesi, in
particolare per quello che riguarda l'aspetto della scrittura dei dati sul
file.

I dati che vengono scritti su di uno \textit{stream} normalmente vengono
accumulati in un buffer e poi trasmessi in blocco, con l'operazione che viene
usualmente chiamata \textsl{scaricamento} del buffer (dal termine inglese
\textit{flush}) tutte le volte che questo viene riempito. Questa operazione
avviene perciò 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 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
scrittura sullo \textit{stream} corrisponda una immediata scrittura sul
dispositivo, e la cosa è particolarmente evidente con le operazioni di
input/output sul terminale.

Per rispondere ad esigenze diverse lo standard definisce tre distinte modalità
in cui può essere eseguita la bufferizzazione, delle quali occorre essere ben
consapevoli, specie in caso di lettura e scrittura da dispositivi interattivi:
\begin{itemize}
\item \textit{unbuffered}: in questo caso non c'è bufferizzazione ed i
  caratteri vengono trasmessi direttamente al file non appena possibile
  (effettuando immediatamente una \func{write});
\item \textit{line buffered}: in questo caso i caratteri vengono normalmente
  trasmessi al file in blocco ogni volta che viene incontrato un carattere di
  \textit{newline} (il carattere ASCII \verb|\n|) cioè un a capo (in sostanza
  quando si preme invio);
\item \textit{fully buffered}: in questo caso i caratteri vengono
  trasmessi da e verso il file in blocchi di dimensione opportuna.
\end{itemize}

Lo standard ANSI C specifica inoltre che lo \itindex{standard~output}
\textit{standard output} e lo \itindex{standard~input} \textit{standard input}
siano aperti in modalità \textit{fully buffered} quando non fanno riferimento
ad un dispositivo interattivo, e che lo standard error non sia mai aperto in
modalità \textit{fully buffered}.

Linux, come BSD e SVr4, specifica il comportamento predefinito in maniera
ancora più precisa, e cioè impone che lo standard error sia sempre
\textit{unbuffered}, in modo che i messaggi di errore siano mostrati il più
rapidamente possibile, e che \itindex{standard~input} \textit{standard input}
e \itindex{standard~output} \textit{standard output} siano aperti in 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 \itindex{standard~input} \textit{standard
  input} e \itindex{standard~output} \textit{standard output} vale anche per
tutti i nuovi \textit{stream} aperti da un processo; la selezione comunque
avviene automaticamente, e la libreria apre lo \textit{stream} nella modalità
più opportuna a seconda del file o del dispositivo scelto.

La modalità \textit{line buffered} è quella che necessita di maggiori
chiarimenti e attenzioni per quel che concerne il suo funzionamento. Come già
accennato nella descrizione, \emph{di norma} i dati vengono inviati al kernel
alla ricezione di un carattere di \textsl{a capo} (il \textit{newline});
questo non è vero in tutti i casi, infatti, dato che le dimensioni del buffer
usato dalle librerie sono fisse, se le si eccedono si può avere uno scarico
dei dati anche prima che sia stato inviato un carattere di \textit{newline}.

Un secondo punto da tenere presente, particolarmente quando si ha a che fare
con I/O interattivo, è che quando si effettua una lettura da uno
\textit{stream} che comporta l'accesso alle \textit{system call} del kernel,
ad esempio se lo \textit{stream} da cui si legge è in modalità
\textit{unbuffered}, viene anche eseguito lo scarico di tutti i buffer degli
\textit{stream} in scrittura. 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.



\subsection{Apertura e chiusura di uno \textit{stream}}
\label{sec:file_fopen}

Le funzioni che si possono usare per aprire uno \textit{stream} sono solo tre:
\funcd{fopen}, \funcd{fdopen} e \funcd{freopen},\footnote{\func{fopen} e
  \func{freopen} fanno parte dello standard ANSI C, \func{fdopen} è parte
  dello standard POSIX.1.} ed i rispettivi prototipi sono:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{FILE *fopen(const char *path, const char *mode)}
\fdesc{Apre uno \textit{stream} da un \texttt{pathname}.} 
\fdecl{FILE *fdopen(int fildes, const char *mode)}
\fdesc{Associa uno \textit{stream} a un file descriptor.} 
\fdecl{FILE *freopen(const char *path, const char *mode, FILE *stream)}
\fdesc{Chiude uno \textit{stream} e lo riapre su un file diverso.} 
}

{Le funzioni ritornano un puntatore ad un oggetto \type{FILE} in caso di
  successo e \val{NULL} per un errore, nel qual 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 \func{fcntl} per
  \func{fdopen} e quelli di \func{fopen}, \func{fclose} e \func{fflush} per
  \func{freopen}.}
\end{funcproto}

Normalmente la funzione che si usa per aprire uno \textit{stream} è
\func{fopen}, essa apre il file specificato dal \textit{pathname} \param{path}
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},
anche se sono possibili varie estensioni che vedremo in seguito.

L'uso più comune di \func{freopen} è per redirigere uno dei tre file standard
(vedi sez.~\ref{sec:file_stream}): il file \param{path} viene aperto nella
modalità indicata da \param{mode} ed associato allo \textit{stream} indicato
dall'argomento \param{stream}, e se questo era uno \textit{stream} già aperto
esso viene preventivamente chiuso e tutti i dati pendenti vengono scaricati.

Infine \func{fdopen} viene usata per associare uno \textit{stream} ad un file
descriptor esistente ottenuto tramite una altra funzione (ad esempio con una
\func{open}, una \func{dup}, o una \func{pipe}) e serve quando si vogliono
usare gli \textit{stream} con file come le fifo o i socket, che non possono
essere aperti con le funzioni delle librerie standard del C.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Valore} & \textbf{Significato}\\
    \hline
    \hline
    \texttt{r} & Il file viene aperto, l'accesso viene posto in sola
                 lettura, lo \textit{stream} è posizionato all'inizio del
                 file.\\ 
    \texttt{r+}& Il file viene aperto, l'accesso viene posto in lettura e
                 scrittura, lo \textit{stream} è posizionato all'inizio del
                 file.\\ 
%    \hline
    \texttt{w} & Il file viene aperto e troncato a lunghezza nulla (o
                 creato se non esiste), l'accesso viene posto in sola
                 scrittura, lo stream\textit{} è posizionato all'inizio del
                 file.\\ 
    \texttt{w+}& Il file viene aperto e troncato a lunghezza nulla (o
                 creato se non esiste), l'accesso viene posto in scrittura e
                 lettura, lo \textit{stream} è posizionato all'inizio del
                 file.\\ 
%    \hline
    \texttt{a} & Il file viene aperto (o creato se non esiste) in
                 \itindex{append~mode} \textit{append mode}, l'accesso viene
                 posto in sola scrittura.\\
    \texttt{a+}& Il file viene aperto (o creato se non esiste) in
                 \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à. \\
    \hline
  \end{tabular}
  \caption{Modalità di apertura di uno \textit{stream} dello standard ANSI C
    che sono sempre presenti in qualunque sistema POSIX.}
  \label{tab:file_fopen_mode}
\end{table}

In realtà lo standard ANSI C prevede un totale di 15 possibili valori
diversi per \param{mode}, ma in 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
distinguere i file binari dai file di testo; in un sistema POSIX questa
distinzione non esiste e il valore viene accettato solo per
compatibilità, ma non ha alcun effetto.

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à 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
valore \verb|STRING| è considerato il nome di una codifica dei caratteri
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
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
\textit{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 automaticamente alla
chiusura dello \textit{stream}.

I nuovi file saranno creati secondo quanto visto in
sez.~\ref{sec:file_ownership_management} 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 della \itindex{umask} \textit{umask}
per il processo (si veda sez.~\ref{sec:file_perm_management}). Una volta
aperto lo \textit{stream}, si può cambiare la modalità di bufferizzazione (si
veda sez.~\ref{sec:file_buffering_ctrl}) fintanto che non si è effettuato
alcuna operazione di I/O sul file.

In caso di file aperti in lettura e scrittura occorre ricordarsi che c'è
di mezzo una bufferizzazione; per questo motivo lo standard ANSI C
richiede che ci sia un'operazione di posizionamento fra un'operazione
di output ed una di input o viceversa (eccetto il caso in cui l'input ha
incontrato la fine del file), altrimenti una lettura può ritornare anche
il risultato di scritture precedenti l'ultima effettuata. 

Per questo motivo è una buona pratica (e talvolta necessario) far seguire ad
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
un'operazione nominalmente nulla come \code{fseek(file, 0, SEEK\_CUR)} è
sufficiente a garantire la sincronizzazione.

Una volta completate le operazioni su di esso uno \textit{stream} può essere
chiuso con la funzione \funcd{fclose}, il cui prototipo è:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{int fclose(FILE *stream)}
\fdesc{Chiude uno \textit{stream}.} 
}

{La funzione ritorna $0$ in caso di successo e \val{EOF} per un errore, nel
  qual caso \var{errno} assumerà il valore \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 \func{fflush}).
}
\end{funcproto}

La funzione chiude lo \textit{stream} \param{stream} ed 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 \textit{stream} questo verrà
rilasciato. La funzione effettua lo scarico solo per i dati presenti nei
buffer in \textit{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 sez.~\ref{sec:file_sync}).

Linux supporta anche una altra funzione, \funcd{fcloseall}, come estensione
GNU implementata dalle \acr{glibc}, accessibile avendo definito
\macro{\_GNU\_SOURCE}, il suo prototipo è:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{int fcloseall(void)}
\fdesc{Chiude tutti gli \textit{stream}.} 
}

{La funzione ritorna $0$ in caso di successo e \val{EOF} per un errore, nel
  qual caso \var{errno} assumerà gli stessi valori di \func{fclose}.}  
\end{funcproto}

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 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_conclusion}).


\subsection{Gestione dell'I/O e posizionamento su uno \textit{stream}}
\label{sec:file_io}

Una delle caratteristiche più utili dell'interfaccia degli \textit{stream} è
la ricchezza delle funzioni disponibili per le operazioni di lettura e
scrittura sui file. Sono infatti previste ben tre diverse modalità modalità di
input/output non formattato:
\begin{itemize}
\item\textsl{binario} in cui si leggono e scrivono blocchi di dati di
   dimensione arbitraria, (analogo della modalità ordinaria dell'I/O sui file
   descriptor), trattato in sez.~\ref{sec:file_binary_io}.
\item\textsl{a caratteri} in cui si legge e scrive un carattere alla volta,
   con la bufferizzazione che viene gestita automaticamente dalla libreria,
   trattato in sez.~\ref{sec:file_char_io}.
\item\textsl{di linea} in cui si legge e scrive una linea alla volta,
   (terminata dal carattere di newline \verb|'\n'|), trattato in
   sez.~\ref{sec:file_line_io}.
\end{itemize}
a cui si aggiunge la modalità di input/output formattato, trattato in
sez.~\ref{sec:file_formatted_io}.

Ognuna di queste modalità utilizza per l'I/O delle funzioni specifiche che
vedremo nelle sezioni citate, affronteremo qui tutte gli argomenti e le
funzioni che si applicano in generale a tutte le modalità di I/O.

A differenza di quanto avviene con l'interfaccia dei file descriptor, con gli
\textit{stream} il raggiungimento della fine del file viene considerato un
errore, e viene notificato come tale dai valori di uscita delle varie
funzioni. Nella maggior parte dei casi questo avviene con la restituzione del
valore intero (di tipo \ctyp{int}) \val{EOF} definito anch'esso nell'header
\headfile{stdlib.h}. La costante deve essere negativa perché in molte funzioni
un valore positivo indica la quantità di dati scritti, le \acr{glibc} usano il
valore $-1$, ma altre implementazioni possono avere valori diversi.

Dato che le funzioni dell'interfaccia degli \textit{stream} sono funzioni di
libreria che si appoggiano a delle \textit{system call}, esse non impostano
direttamente la variabile \var{errno}, che mantiene sempre il valore impostato
dalla \textit{system call} invocata internamente che ha riportato l'errore.

Siccome la condizione di \textit{end-of-file} è anch'essa segnalata come
errore, nasce il problema di come distinguerla da un errore effettivo; basarsi
solo sul valore di ritorno della funzione e controllare il valore di
\var{errno} infatti non basta, dato che quest'ultimo potrebbe essere stato
impostato in 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 mantengono
per ogni \textit{stream} almeno due flag all'interno dell'oggetto \type{FILE},
il flag di \textit{end-of-file}, che segnala che si è raggiunta la fine del
file in lettura, e quello di errore, che segnala la presenza di un qualche
errore nelle operazioni di input/output; questi due flag possono essere
riletti dalle funzioni \funcd{feof} e \funcd{ferror}, i cui prototipi sono:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{int feof(FILE *stream)}
\fdesc{Controlla il flag di \textit{end-of-file} di uno \textit{stream}.} 
\fdecl{int ferror(FILE *stream)}
\fdesc{Controlla il flag di errore di uno \textit{stream}.} 
}

{Le funzioni ritornano un valore diverso da zero se i relativi flag sono
  impostati, e non prevedono condizioni di errore.}
\end{funcproto}

Si tenga presente comunque che la lettura di questi flag segnala soltanto che
c'è stato un errore o che si è raggiunta la fine del file in una qualunque
operazione sullo \textit{stream}, il controllo su quanto avvenuto deve quindi
essere effettuato ogni volta che si chiama una funzione di libreria.

Entrambi i flag (di errore e di \textit{end-of-file}) possono essere
cancellati usando la funzione \funcd{clearerr}, il cui prototipo è:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{void clearerr(FILE *stream)}
\fdesc{Cancella i flag di errore ed \textit{end-of-file} di uno
  \textit{stream}.}
}

{La funzione non ritorna nulla e prevede condizioni di errore.}  
\end{funcproto}

In genere si usa questa funzione una volta che si sia identificata e corretta
la causa di un errore per evitare di mantenere i flag attivi, così da poter
rilevare una successiva ulteriore condizione di errore. Di questa funzione
esiste una analoga \funcm{clearerr\_unlocked} (con lo stesso argomento e
stessi valori di ritorno) che non esegue il blocco dello \textit{stream}
(tratteremo il significato di blocco di uno \textit{stream} in
sez.~\ref{sec:file_stream_thread}).

Come per i file descriptor anche per gli \textit{stream} è possibile spostarsi
all'interno di un file per effettuare operazioni di lettura o scrittura in un
punto prestabilito, sempre che l'operazione di riposizionamento sia supportata
dal file sottostante lo \textit{stream}, nel caso cioè in cui si ha a che
fare con quello che viene detto un file ad \textsl{accesso casuale}. Dato che
in un sistema Unix esistono vari tipi di file, come le fifo ed i
\index{file!di~dispositivo} file di dispositivo (ad esempio i terminali), non
è scontato che questo sia vero in generale, pur essendolo sempre nel caso di
file di dati.

Con Linux ed in generale in ogni sistema unix-like la posizione nel file, come
abbiamo già visto in sez.~\ref{sec:file_lseek}, è espressa da un intero
positivo, rappresentato dal tipo \type{off\_t}. Il problema è che alcune delle
funzioni usate per il riposizionamento sugli \textit{stream} originano dalle
prime versioni di Unix, in cui questo tipo non era ancora stato definito, e
che in altri sistemi non è detto che la posizione su un file venga sempre
rappresentata con il numero di caratteri dall'inizio: ad esempio nel VMS dove
esistono i file a record (in cui cioè l'I/O avviene per blocchi, i record, di
dimensione fissa), essa può essere rappresentata come un numero di record, più
l'offset rispetto al record corrente.

Tutto questo comporta la presenza di diverse funzioni che eseguono
sostanzialmente le stesse operazioni, ma usano argomenti di tipo diverso. Le
funzioni tradizionali usate per eseguire una modifica della posizione corrente
sul file con uno \textit{stream} sono \funcd{fseek} e \funcd{rewind}, i
rispettivi prototipi sono:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{int fseek(FILE *stream, long offset, int whence)}
\fdesc{Sposta la posizione nello \textit{stream}.} 
\fdecl{void rewind(FILE *stream)}
\fdesc{Riporta la posizione nello \textit{stream} all'inizio del file.} 
}

{La funzione \func{fseek} ritorna $0$ in caso di successo e $-1$ per un
  errore, nel qual caso \var{errno} assumerà i valori di \func{lseek},
  \func{rewind} non ritorna nulla e non ha condizioni di errore.}
\end{funcproto}

L'uso di \func{fseek} è del tutto analogo a quello di \func{lseek} per i file
descriptor (vedi sez.~\ref{sec:file_lseek}). Anche gli argomenti, a parte il
tipo, hanno esattamente lo stesso significato. In particolare \param{whence}
deve assumere gli stessi valori già visti nella prima parte di
tab.~\ref{tab:lseek_whence_values}.  La funzione restituisce 0 in caso di
successo e -1 in caso di errore.

La funzione \func{rewind} riporta semplicemente la posizione corrente sul file
all'inizio dello \textit{stream}, ma non è esattamente equivalente ad aver
eseguito una \code{fseek(stream, 0L, SEEK\_SET)}, in quanto con l'uso della
funzione vengono cancellati anche i flag di errore e di fine del file.

Per ottenere la posizione corrente sul file di uno \textit{stream} lo standard
ANSI C prescrive l'uso della funzione \funcd{ftell}, il cui prototipo è:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{long ftell(FILE *stream)} 
\fdesc{Legge la posizione attuale nello \textit{stream}.} 
}

{La funzione ritorna la posizione corrente in caso di successo e $-1$ per un
  errore, nel qual caso \var{errno} assumerà  i valori di \func{lseek}.}  
\end{funcproto}

\noindent che restituisce la posizione come numero di byte dall'inizio dello
\textit{stream}.

Sia \func{fseek} che \func{ftell} esprimono la posizione nel file con un
intero di tipo \ctyp{long}. Dato che in certi casi, ad esempio quando si usa
un filesystem indicizzato a 64 bit su una macchina con architettura a 32 bit,
questo può non essere possibile lo standard POSIX ha introdotto le nuove
funzioni \funcd{fgetpos} e \funcd{fsetpos}, che invece usano il nuovo tipo
\type{fpos\_t}, ed i cui prototipi sono:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{int fsetpos(FILE *stream, fpos\_t *pos)}
\fdesc{Imposta la posizione corrente sul file.} 
\fdecl{int fgetpos(FILE *stream, fpos\_t *pos)}
\fdesc{Legge la posizione corrente sul file.} 
}

{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
  caso \var{errno} assumerà i valori di \func{lseek}.}
\end{funcproto}

In Linux, a partire dalle glibc 2.1, sono presenti anche le due funzioni
\func{fseeko} e \func{ftello}, che sono assolutamente identiche alle
precedenti \func{fseek} e \func{ftell} ma hanno argomenti di tipo
\type{off\_t} anziché di tipo \ctyp{long int}. Dato che \ctyp{long} è nella
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
sistemi più moderni.

% TODO: mettere prototipi espliciti fseeko e ftello o menzione?



\subsection{Input/output binario}
\label{sec:file_binary_io}

La prima modalità di input/output non formattato ricalca quella della
interfaccia dei file descriptor, e provvede semplicemente la scrittura e la
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
funzioni che si usano per l'I/O binario sono \funcd{fread} ed \funcd{fwrite};
i rispettivi prototipi sono:

\begin{funcproto}{
\fhead{stdio.h} 
\fdecl{size\_t fread(void *ptr, size\_t size, size\_t nmemb, FILE *stream)}
\fdesc{Legge i dati da uno \textit{stream}.} 
\fdecl{size\_t fwrite(const void *ptr, size\_t size, size\_t nmemb, 
  FILE *stream)}
\fdesc{Scrive i dati su uno \textit{stream}.} 
}

{Le funzioni ritornano il numero di elementi letti o scritti, in caso di
  errore o fine del file viene restituito un numero di elementi inferiore al
  richiesto.}
\end{funcproto}

Le funzioni rispettivamente leggono e scrivono \param{nmemb} elementi di
dimensione \param{size} dal buffer \param{ptr} al file \param{stream}.  In
genere si usano queste funzioni quando si devono trasferire su file blocchi di
dati binari in maniera compatta e veloce; un primo caso di uso tipico è quello
in cui si salva un vettore (o un certo numero dei suoi elementi) con una
chiamata del tipo:
\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:
\includecodesnip{listati/WriteStruct.c}
in cui si specifica la dimensione dell'intera struttura ed un solo
elemento. 

In realtà quello che conta nel trasferimento dei dati sono le dimensioni
totali, che sono sempre pari al prodotto \code{size * nelem}, la differenza
sta nel fatto che le funzioni non ritornano il numero di byte scritti, ma il
numero di elementi (e con questo possono facilitare i conti).

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
\textit{stream} viene impostata alla fine del file (e non a quella
corrispondente alla quantità di dati letti).

In caso di errore (o fine del file per \func{fread}) entrambe le
funzioni restituiscono il numero di oggetti effettivamente letti o
scritti, che sarà inferiore a quello richiesto. Contrariamente a quanto
avviene per i file descriptor, questo segnala una condizione di errore e
occorrerà usare \func{feof} e \func{ferror} per stabilire la natura del
problema.

Benché queste funzioni assicurino la massima efficienza per il
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
stesso programma che li ha prodotti.

Infatti diversi compilatori possono eseguire ottimizzazioni diverse delle
strutture dati e alcuni compilatori (come il \cmd{gcc}) possono anche
scegliere se ottimizzare l'occupazione di spazio, impacchettando più
strettamente i dati, o la velocità inserendo opportuni \textit{padding} per
l'allineamento dei medesimi generando quindi output binari diversi. Inoltre
altre incompatibilità si possono presentare quando entrano in gioco differenze
di architettura hardware, come la dimensione del bus o la modalità di
ordinamento dei bit o il formato delle variabili in floating point.

Per questo motivo quando si usa l'input/output binario occorre sempre prendere
le opportune precauzioni (in genere usare un formato di più alto livello che
permetta di recuperare l'informazione completa), per assicurarsi che versioni
diverse del programma siano in grado di rileggere i dati tenendo conto delle
eventuali differenze.

Le \acr{glibc} definiscono altre due funzioni per l'I/O binario,
\funcd{fread\_unlocked} e \funcd{fwrite\_unlocked} che evitano il lock
implicito dello \textit{stream}, usato per dalla librerie per la gestione delle
applicazioni \itindex{thread} \textit{multi-thread} (si veda
sez.~\ref{sec:file_stream_thread} per i dettagli), i loro prototipi sono:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{size\_t fread\_unlocked(void *ptr, size\_t size, size\_t
    nmemb, FILE *stream)}
\fdecl{size\_t fwrite\_unlocked(const void *ptr, size\_t size,
    size\_t nmemb, FILE *stream)}
\fdesc{Leggono o scrivono dati su uno \textit{stream} senza acquisire il lock
  implicito sullo stesso.} 
}

{Le funzioni ritornano gli stessi valori delle precedenti \func{fread} e
  \func{fwrite}.}
\end{funcproto}

% TODO: trattare in generale le varie *_unlocked


\subsection{Input/output a caratteri}
\label{sec:file_char_io}

La seconda modalità di input/output è quella a caratteri, in cui si
trasferisce un carattere alla volta.  Le funzioni per la lettura a
caratteri sono tre, \funcd{fgetc}, \funcd{getc} e \funcd{getchar}, ed i
rispettivi prototipi sono:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{int getc(FILE *stream)}
\fdecl{int fgetc(FILE *stream)}
\fdesc{Leggono un singolo byte da uno \textit{stream}.} 
\fdecl{int getchar(void)}
\fdesc{Legge un byte dallo \itindex{standard~input} \textit{standard input}.} 
}

{Le funzioni ritornano il byte letto in caso di successo e \val{EOF} per un
  errore o se si arriva alla fine del file.}  
\end{funcproto}

La funzione \func{getc} legge un byte da \param{stream} e lo restituisce come
intero, ed in genere è implementata come una macro per cui può avere
\itindex{side~effects} \textit{side effects}, mentre \func{fgetc} è assicurato
essere sempre una funzione. Infine \func{getchar} è equivalente a
\code{getc(stdin)}.

A parte \func{getchar}, che si usa in genere per leggere un carattere da
tastiera, le altre due funzioni sono sostanzialmente equivalenti. La
differenza è che \func{getc} è ottimizzata al massimo e normalmente
viene implementata con una macro, per cui occorre stare attenti a cosa
le si passa come argomento, infatti \param{stream} può essere valutato
più volte nell'esecuzione, e non viene passato in copia con il
meccanismo visto in sez.~\ref{sec:proc_var_passing}; per questo motivo se
si passa un'espressione si possono avere effetti indesiderati.

Invece \func{fgetc} è assicurata essere sempre una funzione, per questo motivo
la sua esecuzione normalmente è più lenta per via dell'overhead della
chiamata, ma è altresì possibile ricavarne l'indirizzo, che può essere passato
come 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
l'espansione del segno). In questo modo il valore di ritorno è sempre
positivo, tranne in caso di errore o fine del file.

Nelle estensioni GNU che provvedono la localizzazione sono definite tre
funzioni equivalenti alle precedenti, \funcd{getwc}, \funcd{fgetwc} e
\funcd{getwchar}, che invece di un carattere di un byte restituiscono un
carattere in formato esteso (cioè di tipo \ctyp{wint\_t}), il loro prototipo
è:

\begin{funcproto}{
\fhead{stdio.h} 
\fhead{wchar.h}
\fdecl{wint\_t getwc(FILE *stream)}
\fdecl{wint\_t fgetwc(FILE *stream)}
\fdesc{Leggono un carattere da uno \textit{stream}.} 
\fdecl{wint\_t getwchar(void)}
\fdesc{Legge un carattere dallo \itindex{standard~input} \textit{standard
    input}.} 
}

{Le funzioni ritornano il carattere letto in caso di successo e \val{WEOF} per
  un errore o se si arriva alla fine del file.}  
\end{funcproto}

La funzione \func{getwc} legge un carattere esteso da \param{stream} e lo
restituisce come intero, ed in genere è implementata come una macro, mentre
\func{fgetwc} è assicurata essere sempre una funzione. Infine \func{getwchar}
è equivalente a \code{getwc(stdin)}.

Per scrivere un carattere si possono usare tre funzioni, analoghe alle
precedenti usate per leggere: \funcd{putc}, \funcd{fputc} e \funcd{putchar}; i
loro prototipi sono:

\begin{funcproto}{
\fhead{stdio.h} 
\fdecl{int putc(int c, FILE *stream)}
\fdecl{int fputc(int c, FILE *stream)}
\fdesc{Scrive un byte su uno \textit{stream}.}
\fdecl{int putchar(int c)}
\fdesc{Scrive un byte sullo  \itindex{standard~output} \textit{standard
    output}.}
}

{Le funzioni ritornano il valore del byte scritto in caso di successo e
  \val{EOF} per un errore.}  
\end{funcproto}

La funzione \func{putc} scrive un byte su \param{stream} e lo restituisce come
intero, ed in genere è implementata come una macro, mentre \func{fputc} è
assicurata essere sempre una funzione. Infine \func{putchar} è equivalente a
\code{putc(stdout)}.  Tutte queste funzioni scrivono sempre un byte alla
volta, anche se prendono come argomento un \ctyp{int} (che pertanto deve
essere ottenuto con un cast da un \ctyp{unsigned char}). Anche il valore di
ritorno è sempre un intero; in caso di errore o fine del file il valore di
ritorno è \val{EOF}.

Come nel caso dell'I/O binario con \func{fread} e \func{fwrite} le \acr{glibc}
provvedono come estensione, per ciascuna delle funzioni precedenti,
un'ulteriore funzione, il cui nome è ottenuto aggiungendo un
\code{\_unlocked}, che esegue esattamente le stesse operazioni, evitando però
il lock implicito dello \textit{stream}.

Per compatibilità con SVID sono inoltre provviste anche due funzioni,
\funcd{getw} e \funcd{putw}, da usare per leggere e scrivere una \textit{word}
(cioè due byte in una volta); i loro prototipi sono:

\begin{funcproto}{
\fhead{stdio.h} 
\fdecl{getw(FILE *stream)}
\fdesc{Legge una parola da uno \textit{stream}.} 
\fdecl{int putw(int w, FILE *stream)}
\fdesc{Scrive una parola su uno \textit{stream}.} 
}

{Le funzioni ritornano la parola letta o scritta in caso di successo e
  \val{EOF} per un errore.}
\end{funcproto}

Le funzioni leggono e scrivono una \textit{word} di due byte, usando comunque
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
valore -1 da una condizione di errore che restituisce \val{EOF}.

Uno degli usi più frequenti dell'input/output a caratteri è nei programmi di
\textit{parsing} in cui si analizza il testo; in questo contesto diventa utile
poter analizzare il carattere successivo da uno \textit{stream} senza estrarlo
effettivamente (la tecnica è detta \textit{peeking ahead}) in modo che il
programma possa regolarsi avendo dato una \textsl{sbirciatina} a quello che
viene dopo.

Nel nostro caso questo tipo di comportamento può essere realizzato prima
leggendo il carattere, e poi rimandandolo indietro, cosicché ridiventi
disponibile per una lettura successiva; la funzione che inverte la
lettura si chiama \funcd{ungetc} ed il suo prototipo è:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{int ungetc(int c, FILE *stream)}
\fdesc{Manda indietro un byte su uno \textit{stream}.} 
}

{La funzione ritorna il byte inviato in caso di successo e \val{EOF} per un
  errore.}  
\end{funcproto}
 
La funzione rimanda indietro il carattere \param{c}, con un cast a
\ctyp{unsigned char}, sullo \textit{stream} \param{stream}. Benché lo standard
ANSI C preveda che l'operazione possa essere ripetuta per un numero arbitrario
di caratteri, alle implementazioni è richiesto di garantire solo un livello;
questo è 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 essere usata per rimandare
indietro l'ultimo carattere letto.  Nel caso \param{c} sia un \val{EOF} la
funzione non fa nulla, e restituisce sempre \val{EOF}; così si può usare
\func{ungetc} anche con il risultato di una lettura alla fine del file.

Se si è alla fine del file si può comunque rimandare indietro un carattere, il
flag di \textit{end-of-file} verrà automaticamente cancellato perché c'è un
nuovo carattere disponibile che potrà essere riletto 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 sez.~\ref{sec:file_io}) i caratteri
rimandati indietro vengono scartati.


\subsection{Input/output di linea}
\label{sec:file_line_io}

La terza ed ultima modalità di input/output non formattato è quella di linea,
in cui si legge o si scrive una riga alla volta. Questa è la modalità usata
normalmente per l'I/O da terminale, ed è 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
prototipi sono:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{char *gets(char *string)}
\fdesc{Legge una linea di testo dallo \itindex{standard~input}
  \textit{standard input}.}
\fdecl{char *fgets(char *string, int size, FILE *stream)}
\fdesc{Legge una linea di testo da uno \textit{stream}.} 
}

{Le funzioni ritornano l'indirizzo della stringa con la linea di testo letta o
  scritta in caso di successo e \val{NULL} per un errore.}
\end{funcproto}
 
Entrambe le funzioni effettuano la lettura, dal file specificato \func{fgets},
dallo \itindex{standard~input} \textit{standard input} \func{gets}, di una
linea di caratteri terminata dal carattere ASCII di \textit{newline}, che come
detto corrisponde a quello generato dalla pressione del tasto di invio sulla
tastiera. Si tratta del carattere che indica la terminazione di una riga (in
sostanza del carattere di ``\textsl{a capo}'') che viene rappresentato nelle
stringhe di formattazione che vedremo in sez.~\ref{sec:file_formatted_io} come
``\verb|\n|''. Nell'esecuzione delle funzioni \func{gets} sostituisce
``\verb|\n|'' con uno zero, mentre \func{fgets} aggiunge uno zero dopo il
\textit{newline}, che resta dentro la stringa.

Se la lettura incontra la fine del file (o c'è un errore) viene restituito un
puntatore \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 \itindex{buffer~overflow}
\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 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, che in
genere contiene uno \textit{shell code}, cioè una sezione di programma che
lancia una shell da cui si potranno poi eseguire altri programmi.

La funzione \func{fgets} non ha i precedenti problemi di \func{gets} in quanto
prende in ingresso la dimensione del buffer \param{size}, che non verrà mai
ecceduta in lettura. La funzione legge fino ad un massimo di \param{size}
caratteri (\textit{newline} compreso), ed aggiunge uno zero di terminazione;
questo comporta che la stringa possa essere al massimo di \code{size-1}
caratteri.  Se la linea eccede la dimensione del buffer verranno letti solo
\code{size-1} caratteri, ma la stringa sarà sempre terminata correttamente con
uno zero finale; sarà possibile leggere i rimanenti caratteri in una chiamata
successiva.

Per la scrittura di una linea lo standard ANSI C prevede altre due
funzioni, \funcd{fputs} e \funcd{puts}, analoghe a quelle di lettura, i
rispettivi prototipi sono:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{int puts(char *string)}
\fdesc{Scrive una linea di testo sullo  \itindex{standard~output}
  \textit{standard output}.}
\fdecl{int fputs(char *string, int size, FILE *stream)}
\fdesc{Scrive una linea di testo su uno \textit{stream}.} 
}

{Le funzioni ritornano un valore non negativo in caso di successo e \val{EOF}
  per un errore.}
\end{funcproto}

La funzione \func{puts} scrive una linea di testo mantenuta
all'indirizzo \param{string} sullo \itindex{standard~output} \textit{standard
  output} mentre \func{puts} la scrive sul file indicato da \param{stream}.
Dato che in questo caso si scrivono i dati in uscita \func{puts} non ha i
problemi di \func{gets} ed è in genere la forma più immediata per scrivere
messaggi sullo \itindex{standard~output} \textit{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 \textit{newline}, che deve essere previsto esplicitamente.

Come per le analoghe funzioni di input/output a caratteri, anche per l'I/O di
linea esistono delle estensioni per leggere e scrivere linee di caratteri
estesi, le funzioni in questione sono \funcd{fgetws} e \funcd{fputws} ed i
loro prototipi sono:

\begin{funcproto}{
\fhead{wchar.h}
\fdecl{wchar\_t *fgetws(wchar\_t *ws, int n, FILE *stream)}
\fdesc{Legge una stringa di carattere estesi da uno \textit{stream}.} 
\fdecl{int fputws(const wchar\_t *ws, FILE *stream)}
\fdesc{Scrive una stringa di carattere estesi da uno \textit{stream}.} 
}

{Le funzioni ritornano rispettivamente l'indirizzo della stringa o un non
  negativo in caso di successo e \val{NULL} o \val{EOF} per un errore o per la
  fine del file.}
\end{funcproto}


La funzione \func{fgetws} legge un massimo di \param{n} caratteri estesi dal
file \param{stream} al buffer \param{ws}, mentre la funzione \func{fputws}
scrive la linea \param{ws} di caratteri estesi sul file indicato
da \param{stream}.  Il comportamento di queste due funzioni è identico a
quello di \func{fgets} e \func{fputs}, a parte il fatto che tutto (numero di
caratteri massimo, terminatore della stringa, \textit{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
esattamente le stesse operazioni delle loro equivalenti, evitando però il lock
implicito dello \textit{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ò 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 \textit{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 che eccede le dimensioni del buffer.

Per questo motivo le \acr{glibc} prevedono, come estensione GNU, due nuove
funzioni per la gestione dell'input/output di linea, il cui uso permette di
risolvere questi problemi. L'uso di queste funzioni deve essere attivato
definendo la macro \macro{\_GNU\_SOURCE} prima di includere
\headfile{stdio.h}. La prima delle due, \funcd{getline}, serve per leggere una
linea terminata da un \textit{newline}, esattamente allo stesso modo di
\func{fgets}, il suo prototipo è:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{ssize\_t getline(char **buffer, size\_t *n, FILE *stream)}
\fdesc{Legge una riga da uno \textit{stream}.} 
}

{La funzione ritorna il numero di caratteri letti in caso di successo e $-1$
  per un errore o per il raggiungimento della fine del file.}
\end{funcproto}

La funzione legge una linea dal file \param{stream} copiandola sul buffer
indicato da \param{buffer} riallocandolo se necessario (l'indirizzo del buffer
e la sua dimensione vengono sempre riscritte). Permette così di eseguire una
lettura senza doversi preoccupare della 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 \func{malloc}, non si può cioè passare come argomento primo
argomento l'indirizzo di un puntatore ad una variabile locale. Come secondo
argomento la funzione vuole l'indirizzo della variabile contenente le
dimensioni del buffer suddetto.

Se il buffer di destinazione è sufficientemente ampio la stringa viene scritta
subito, altrimenti il buffer viene allargato usando \func{realloc} e la nuova
dimensione ed il nuovo puntatore vengono restituiti indietro, si noti infatti
come entrambi gli argomenti siano dei \itindex{value~result~argument}
\textit{value result argument}, per i quali vengono passati dei puntatori
anziché i valori delle variabili, secondo quanto abbiamo descritto 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
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 \itindex{memory~leak} \textit{memory leak} occorre ricordarsi di
liberare la memoria allocata dalla funzione eseguendo una \func{free} su
\var{ptr}.

Il valore di ritorno di \func{getline} indica il numero di caratteri letti
dallo \textit{stream}, quindi compreso il \textit{newline}, ma non lo zero di
terminazione. Questo permette anche di distinguere anche gli eventuali zeri
letti come dati dallo \textit{stream} da quello inserito dalla funzione dopo
il \textit{newline} per terminare la stringa.  Se si è alla fine del file e
non si è potuto leggere nulla o se c'è stato un errore la funzione restituisce
$-1$.

La seconda estensione GNU per la lettura con l'I/O di linea è una
generalizzazione di \func{getline} per poter usare come separatore delle linee
un carattere qualsiasi al posto del \textit{newline}. La funzione si chiama
\funcd{getdelim} ed il suo prototipo è:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{size\_t getdelim(char **buffer, size\_t *n, int delim, FILE *stream)} 
\fdesc{Legge da uno \textit{stream} una riga delimitata da un carattere
  scelto.} 
}

{La funzione ha gli stessi valori di ritorno e gli stessi errori di
  \func{getline}.}
\end{funcproto}

La funzione è identica a \func{getline} solo che usa \param{delim} al posto
del carattere di \textit{newline} come separatore di linea. Il comportamento
di \func{getdelim} è identico a quello di \func{getline}, che può essere
implementata da \func{getdelim} passando ``\verb|\n|'' come valore
dell'argomento \param{delim}.


\subsection{Input/output formattato}
\label{sec:file_formatted_io}

L'ultima modalità di input/output è quella formattata, che è una delle
caratteristiche più utilizzate delle librerie standard del C; in genere questa
è la modalità in cui si esegue normalmente l'output su terminale poiché
permette di stampare in maniera facile e veloce dati, tabelle e messaggi.

L'output formattato viene eseguito con una delle 13 funzioni della famiglia
\func{printf}; le tre più usate sono \funcd{printf}, \funcd{fprintf} e
\funcd{sprintf}, i cui prototipi sono:

\begin{funcproto}{
\fhead{stdio.h} 
\fdecl{int printf(const char *format, ...)}
\fdesc{Scrive una stringa formattata sullo \itindex{standard~output}
  \textit{standard output}.}
\fdecl{int fprintf(FILE *stream, const char *format, ...)}
\fdesc{Scrive una stringa formattata su uno \textit{stream}.} 
\fdecl{int sprintf(char *str, const char *format, ...)} 
\fdesc{Scrive una stringa formattata su un buffer.} 
}

{Le funzioni ritornano il numero di caratteri scritti in caso di successo e un
  valore negativo per un errore.}  
\end{funcproto}


Le funzioni usano la stringa \param{format} come indicatore del formato con
cui dovrà essere scritto il contenuto degli argomenti, il cui numero
\index{funzioni!variadic} è variabile e dipende dal formato stesso.

Le prime due servono per scrivere su file (lo \itindex{standard~output}
\textit{standard output} o quello specificato) la terza permette di scrivere
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 \itindex{buffer~overflow}
\textit{buffer overflow}. Per questo motivo si consiglia l'uso
dell'alternativa \funcd{snprintf}, il cui prototipo è:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{snprintf(char *str, size\_t size, const char *format, ...)} 
\fdesc{Scrive una stringa formattata su un buffer.} 
}

{La funzione ha lo stesso valore di ritorno e gli stessi errori di
  \func{sprintf}.}
\end{funcproto}

\noindent la funzione è identica a \func{sprintf}, ma non scrive
su \param{str} più di \param{size} caratteri, garantendo così che il buffer
non possa essere sovrascritto.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|l|p{10cm}|}
    \hline
    \textbf{Valore} & \textbf{Tipo} & \textbf{Significato} \\
    \hline
    \hline
   \cmd{\%d} &\ctyp{int}         & Stampa un numero intero in formato decimale
                                   con segno.\\
   \cmd{\%i} &\ctyp{int}         & Identico a \cmd{\%d} in output.\\
   \cmd{\%o} &\ctyp{unsigned int}& Stampa un numero intero come ottale.\\
   \cmd{\%u} &\ctyp{unsigned int}& Stampa un numero intero in formato
                                   decimale senza segno.\\
   \cmd{\%x}, 
   \cmd{\%X} &\ctyp{unsigned int}& Stampano un intero in formato esadecimale,
                                   rispettivamente con lettere minuscole e
                                   maiuscole.\\
   \cmd{\%f} &\ctyp{double}      & Stampa un numero in virgola mobile con la
                                   notazione a virgola fissa.\\
   \cmd{\%e}, 
   \cmd{\%E} &\ctyp{double} & Stampano un numero in virgola mobile con la
                              notazione esponenziale, rispettivamente con
                              lettere minuscole e maiuscole.\\
   \cmd{\%g}, 
   \cmd{\%G} &\ctyp{double} & Stampano un numero in virgola mobile con la
                              notazione più appropriate delle due precedenti,
                              rispettivamente con lettere minuscole e
                              maiuscole.\\
   \cmd{\%a}, 
   \cmd{\%A} &\ctyp{double} & Stampano un numero in virgola mobile in
                              notazione esadecimale frazionaria.\\
   \cmd{\%c} &\ctyp{int}    & Stampa un carattere singolo.\\
   \cmd{\%s} &\ctyp{char *} & Stampa una stringa.\\
   \cmd{\%p} &\ctyp{void *} & Stampa il valore di un puntatore.\\
   \cmd{\%n} &\ctyp{\&int}  & Prende il numero di caratteri stampati finora.\\
   \cmd{\%\%}&              & Stampa un ``\texttt{\%}''.\\
    \hline
  \end{tabular}
  \caption{Valori possibili per gli specificatori di conversione in una
    stringa di formato di \func{printf}.} 
  \label{tab:file_format_spec}
\end{table}

La parte più complessa delle funzioni di scrittura formattata è il formato
della stringa \param{format} che indica le conversioni da fare, e da cui
deriva anche il numero degli argomenti che dovranno essere passati a seguire:
si noti come tutte queste funzioni siano \index{funzioni!variadic}
\textit{variadic}, prendendo un numero di argomenti variabile che dipende
appunto da quello che si è specificato in \param{format}.

La stringa di formato è costituita da caratteri normali (tutti eccetto
``\texttt{\%}''), che vengono passati invariati all'output, e da direttive di
conversione, in cui devono essere sempre presenti il carattere
``\texttt{\%}'', che introduce la direttiva, ed uno degli specificatori di
conversione (riportati in tab.~\ref{tab:file_format_spec}) che la conclude.

Il formato di una direttiva di conversione prevede una serie di possibili
elementi opzionali oltre al carattere ``\cmd{\%}'' e allo specificatore di
conversione. In generale essa è sempre del tipo:
\begin{Example}
% [n. parametro $] [flag] [[larghezza] [. precisione]] [tipo] conversione
\end{Example}
in cui tutti i valori tranne il ``\texttt{\%}'' e lo specificatore di
conversione sono opzionali (e per questo sono indicati fra parentesi quadre);
si possono usare più elementi opzionali, nel qual caso devono essere
specificati in questo ordine:
\begin{itemize*}
\item uno specificatore del parametro da usare (terminato da un carattere
  ``\val{\$}''),
\item uno o più flag (i cui valori possibili sono riassunti in
  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 tab.~\ref{tab:file_format_type}).
\end{itemize*}

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Valore} & \textbf{Significato}\\
    \hline
    \hline
    \val{\#} & Chiede la conversione in forma alternativa.\\
    \val{0}  & La conversione è riempita con zeri alla sinistra del valore.\\
    \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{+}  & Mette sempre il segno ($+$ o $-$) prima di un numero.\\
    \hline
  \end{tabular}
  \caption{I valori dei flag per il formato di \func{printf}}
  \label{tab:file_format_flag}
\end{table}

Dettagli ulteriori sulle varie opzioni di stampa e su tutte le casistiche
dettagliate dei vari formati possono essere trovati nella pagina di manuale di
\func{printf} e nella documentazione delle \acr{glibc}.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Valore} & \textbf{Significato} \\
    \hline
    \hline
    \cmd{hh} & Una conversione intera corrisponde a un \ctyp{char} con o senza
               segno, o il puntatore per il numero dei parametri \cmd{n} è di 
               tipo \ctyp{char}.\\
    \cmd{h}  & Una conversione intera corrisponde a uno \ctyp{short} con o 
               senza segno, o il puntatore per il numero dei parametri \cmd{n}
               è di tipo \ctyp{short}.\\
    \cmd{l}  & Una conversione intera corrisponde a un \ctyp{long} con o 
               senza segno, o il puntatore per il numero dei parametri \cmd{n}
               è di tipo \ctyp{long}, o il carattere o la stringa seguenti
               sono in formato esteso.\\ 
    \cmd{ll} & Una conversione intera corrisponde a un \ctyp{long long} con o 
               senza segno, o il puntatore per il numero dei parametri \cmd{n}
               è di tipo \ctyp{long long}.\\
    \cmd{L}  & Una conversione in virgola mobile corrisponde a un
               \ctyp{double}.\\
    \cmd{q}  & Sinonimo di \cmd{ll}.\\
    \cmd{j}  & Una conversione intera corrisponde a un \type{intmax\_t} o 
               \type{uintmax\_t}.\\
    \cmd{z}  & Una conversione intera corrisponde a un \type{size\_t} o 
               \type{ssize\_t}.\\
    \cmd{t}  & Una conversione intera corrisponde a un \type{ptrdiff\_t}.\\
    \hline
  \end{tabular}
  \caption{Il modificatore di tipo di dato per il formato di \func{printf}}
  \label{tab:file_format_type}
\end{table}

Una versione alternativa delle funzioni di output formattato, che permettono
di usare il puntatore ad una lista variabile di argomenti (vedi
sez.~\ref{sec:proc_variadic}), sono \funcd{vprintf}, \funcd{vfprintf} e
\funcd{vsprintf}, i cui prototipi sono:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{int vprintf(const char *format, va\_list ap)}
\fdesc{Scrive una stringa formattata sullo \itindex{standard~output}
  \textit{standard output}.} 
\fdecl{int vfprintf(FILE *stream, const char *format, va\_list ap)}
\fdesc{Scrive una stringa formattata su uno \textit{stream}.}
\fdecl{int vsprintf(char *str, const char *format, va\_list ap)}
\fdesc{Scrive una stringa formattata su un buffer.}
}

{Le funzioni ritornano il numero di caratteri scritti in caso di successo e un
  valore negativo per un errore.}  
\end{funcproto}

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
variabile\index{funzioni!variadic} degli argomenti dovrà essere opportunamente
trattata (l'argomento è esaminato in sez.~\ref{sec:proc_variadic}), e dopo
l'esecuzione della funzione l'argomento
\param{ap} non sarà più utilizzabile (in generale dovrebbe essere eseguito un
\code{va\_end(ap)} ma in Linux questo non è necessario). 

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{funcproto}{
\fhead{stdio.h}
\fdecl{vsnprintf(char *str, size\_t size, const char *format, va\_list ap)}
\fdesc{Scrive una stringa formattata su un buffer.} 
}

{La funzione ha lo stesso valore di ritorno e gli stessi errori di
  \func{vsprintf}.}
\end{funcproto}

\noindent in modo da evitare possibili \itindex{buffer~overflow} buffer
overflow.


Per eliminare alla radice questi problemi, la \acr{glibc} supporta una
specifica estensione GNU che alloca dinamicamente tutto lo spazio necessario;
l'estensione si attiva al solito definendo \macro{\_GNU\_SOURCE}, le due
funzioni sono \funcd{asprintf} e \funcd{vasprintf}, ed i rispettivi prototipi
sono:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{int asprintf(char **strptr, const char *format, ...)}
\fdecl{int vasprintf(char **strptr, const char *format, va\_list ap)}
\fdesc{Scrive una stringa formattata su un buffer.} 
}

{Le funzioni hanno lo stesso valore di ritorno e gli stessi errori di
  \func{vsprintf}.}
\end{funcproto}


Entrambe le funzioni prendono come argomento \param{strptr} che deve essere
l'indirizzo di un puntatore ad una stringa di caratteri, in cui verrà
restituito (si ricordi quanto detto in sez.~\ref{sec:proc_var_passing} a
proposito dei \itindex{value~result~argument} \textit{value result argument})
l'indirizzo della stringa allocata automaticamente dalle funzioni. Occorre
inoltre ricordarsi di invocare \func{free} per liberare detto puntatore quando
la stringa non serve più, onde evitare \itindex{memory~leak} \textit{memory
  leak}.

% TODO verificare se mettere prototipi di \func{dprintf} e \func{vdprintf}

Infine una ulteriore estensione GNU definisce le due funzioni \funcm{dprintf} e
\funcm{vdprintf}, che prendono un file descriptor al posto dello
\textit{stream}. Altre estensioni permettono di scrivere con caratteri
estesi. Anche queste funzioni, il cui nome è generato dalle precedenti
funzioni aggiungendo una \texttt{w} davanti a \texttt{print}, sono trattate in
dettaglio nella documentazione delle \acr{glibc}.

In corrispondenza alla famiglia di funzioni \func{printf} che si usano per
l'output formattato, l'input formattato viene eseguito con le funzioni della
famiglia \func{scanf}; fra queste le tre più importanti sono \funcd{scanf},
\funcd{fscanf} e \funcd{sscanf}, i cui prototipi sono:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{int scanf(const char *format, ...)}
\fdesc{Esegue la scansione di dati dallo \itindex{standard~input}
  \textit{standard input}.}
\fdecl{int fscanf(FILE *stream, const char *format, ...)}
\fdesc{Esegue la scansione di dati da uno \textit{stream}. } 
\fdecl{int sscanf(char *str, const char *format, ...)}
\fdesc{Esegue la scansione di dati da un buffer.} 
}

{La funzione ritorna il numero di elementi assegnati in caso di successo e
  \val{EOF} per un errore o se si raggiunta la fine del file.}
\end{funcproto}

Le funzioni eseguono una scansione della rispettiva fonte di input cercando
una corrispondenza di quanto letto con il formato dei dati specificato
da \param{format}, ed effettua le relative conversioni memorizzando il
risultato negli argomenti seguenti, il cui numero è variabile e dipende dal
valore di \param{format}. Come per le analoghe funzioni di scrittura esistono
le relative \funcm{vscanf}, \funcm{vfscanf} e \funcm{vsscanf} che usano un
puntatore ad una lista di argomenti. Le funzioni ritornano il numero di
elementi assegnati. Questi possono essere in numero inferiore a quelli
specificati, ed anche zero. Quest'ultimo valore significa che non si è trovata
corrispondenza.

Tutte le funzioni della famiglia delle \func{scanf} vogliono come argomenti i
puntatori alle variabili che dovranno contenere le conversioni; questo è un
primo elemento di disagio in quanto è molto facile dimenticarsi di questa
caratteristica.

Le funzioni leggono i caratteri dallo \textit{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 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 caratteri diversi richiedono una corrispondenza
esatta. Le direttive di conversione sono analoghe a quelle di \func{printf} e
si trovano descritte in dettaglio nelle pagine di manuale e nel manuale delle
\acr{glibc}.

Le funzioni eseguono la lettura dall'input, scartano i separatori (e gli
eventuali caratteri diversi indicati dalla stringa di formato) effettuando le
conversioni richieste; in caso la corrispondenza fallisca (o la funzione non
sia in grado di effettuare una delle conversioni richieste) la scansione viene
interrotta immediatamente e la funzione ritorna lasciando posizionato lo
\textit{stream} al primo carattere che non corrisponde.

Data la notevole complessità di uso di queste funzioni, che richiedono molta
cura nella definizione delle corrette stringhe di formato e sono facilmente
soggette ad errori, e considerato anche il fatto che è estremamente macchinoso
recuperare in caso di fallimento nelle corrispondenze, l'input formattato non
è molto usato. In genere infatti quando si ha a che fare con un input
relativamente semplice si preferisce usare l'input di linea ed effettuare
scansione e conversione di quanto serve direttamente con una delle funzioni di
conversione delle stringhe; se invece il formato è più complesso diventa più
facile utilizzare uno strumento come \cmd{flex}\footnote{il programma
  \cmd{flex}, è una implementazione libera di \cmd{lex} un generatore di
  analizzatori lessicali. Per i dettagli si può fare riferimento al manuale
  \cite{flex}.} per generare un analizzatore lessicale o 
\cmd{bison}\footnote{il programma \cmd{bison} è un clone del generatore di
  parser \cmd{yacc}, maggiori dettagli possono essere trovati nel relativo
  manuale \cite{bison}.} per generare un parser.



\section{Funzioni avanzate}
\label{sec:file_stream_adv_func}

In questa sezione esamineremo alcune funzioni avanzate che permettono di
eseguire operazioni di basso livello nella gestione degli \textit{stream},
come leggerne gli attributi, controllarne le modalità di bufferizzazione,
gestire in maniera esplicita i lock impliciti presenti ad uso della
programmazione \itindex{thread} \textit{multi-thread}.


\subsection{Le funzioni di controllo}
\label{sec:file_stream_cntrl}

Al contrario di quanto avviene con i file descriptor, le librerie standard del
C non prevedono nessuna funzione come la \func{fcntl} per il controllo degli
attributi dei file. Però, dato che ogni \textit{stream} si appoggia ad un file
descriptor, si può usare la funzione \funcd{fileno} per ottenere il valore di
quest'ultimo; il suo prototipo è:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{int fileno(FILE *stream)}
\fdesc{Legge il file descriptor sottostante lo \textit{stream}.} 
}

{La funzione ritorna il numero del file descriptor in caso di successo e $-1$
  per un errore, nel qual caso \var{errno} assumerà il valore \errval{EBADF}
  se \param{stream} non è valido.}
\end{funcproto}

In questo modo diventa possibile usare direttamente \func{fcntl} sul file
descriptor sottostante, ma anche se questo permette di accedere agli attributi
del file descriptor sottostante lo \textit{stream}, non ci dà nessuna
informazione riguardo alle proprietà dello \textit{stream} medesimo.  Le
\acr{glibc} però supportano alcune estensioni derivate da Solaris, che
permettono di ottenere informazioni utili relative allo \textit{stream}.

Ad esempio in certi casi può essere necessario sapere se un certo
\textit{stream} è accessibile in lettura o scrittura. In genere questa
informazione non è disponibile, e ci si deve ricordare come è stato aperto il
file. La cosa può essere complessa se le operazioni vengono effettuate in una
subroutine, che a questo punto necessiterà di informazioni aggiuntive rispetto
al semplice puntatore allo \textit{stream}. Questo problema può essere risolto
con le due funzioni \funcd{\_\_freadable} e \funcd{\_\_fwritable} i cui
prototipi sono:

\begin{funcproto}{
\fhead{stdio\_ext.h}
\fdecl{int \_\_freadable(FILE *stream)}
\fdesc{Controlla se uno \textit{stream} consente la lettura.} 
\fdecl{int \_\_fwritable(FILE *stream)}
\fdesc{Controlla se uno \textit{stream} consente la scrittura.} 
}

{Le funzioni ritornano un valore diverso da $0$ se l'operazione richiesta è
  consentita, non sono previste condizioni di errore.}  
\end{funcproto}

\noindent che permettono di ottenere questa informazione.

La conoscenza dell'ultima operazione effettuata su uno \textit{stream} aperto
è utile in quanto permette di trarre conclusioni sullo stato del buffer e del
suo contenuto. Altre due funzioni, \funcd{\_\_freading} e \funcd{\_\_fwriting}
servono a tale scopo, il loro prototipo è:

\begin{funcproto}{
\fhead{stdio\_ext.h}
\fdecl{int \_\_freading(FILE *stream)}
\fdesc{Controlla l'ultima operazione di lettura.}
\fdecl{int \_\_fwriting(FILE *stream)}
\fdesc{Controlla l'ultima operazione di scrittura.}
}

{Le funzioni ritornano un valore diverso da $0$ se l'operazione richiesta è
  consentita, non sono previste condizioni di errore.}
\end{funcproto}

La funzione \func{\_\_freading} restituisce un valore diverso da zero
se \param{stream} è aperto in sola lettura o se l'ultima operazione è stata di
lettura mentre \func{\_\_fwriting} restituisce un valore diverso da zero
se \param{stream} è aperto in sola scrittura o se l'ultima operazione è stata
di scrittura.

Le due funzioni permettono di determinare di che tipo è stata l'ultima
operazione eseguita su uno \textit{stream} aperto in lettura/scrittura;
ovviamente se uno \textit{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.


\subsection{Il controllo della bufferizzazione}
\label{sec:file_buffering_ctrl}

Come accennato in sez.~\ref{sec:file_buffering} le librerie definiscono una
serie di funzioni che permettono di controllare il comportamento degli
\textit{stream}; se non si è specificato nulla, la modalità di buffering viene
decisa autonomamente sulla base del tipo di file sottostante, ed i buffer
vengono allocati automaticamente.

Però una volta che si sia aperto lo \textit{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
cui prototipo è:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{int setvbuf(FILE *stream, char *buf, int mode, size\_t size)}
\fdesc{Imposta la bufferizzazione dello \textit{stream}.} 
}

{La funzione ritorna $0$ in caso di successo e un altro valore qualunque per
  un errore, nel qual caso \var{errno} assumerà un valore appropriato.}  
\end{funcproto}

La funzione imposta la bufferizzazione dello \textit{stream} \param{stream}
nella modalità indicata da \param{mode} con uno dei valori di
tab.~\ref{tab:file_stream_buf_mode}, usando \param{buf} come buffer di
lunghezza \param{size} e permette di controllare tutti gli aspetti della
bufferizzazione. L'utente può specificare un buffer da usare al posto di
quello allocato dal sistema passandone alla funzione l'indirizzo
in \param{buf} e la dimensione in \param{size}.

\begin{table}[htb]
  \centering
  \footnotesize
    \begin{tabular}[c]{|l|l|}
      \hline
      \textbf{Valore} & \textbf{Modalità} \\
      \hline
      \hline
      \const{\_IONBF} & \textit{unbuffered}\\
      \const{\_IOLBF} & \textit{line buffered}\\
      \const{\_IOFBF} & \textit{fully buffered}\\
      \hline
    \end{tabular}
    \caption{Valori dell'argomento \param{mode} di \func{setvbuf} 
      per l'impostazione delle modalità di bufferizzazione.}
  \label{tab:file_stream_buf_mode}
\end{table}

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
\textit{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 \index{variabili!automatiche} variabile
automatica. In \headfile{stdio.h} è definita la macro \const{BUFSIZ}, che
indica le dimensioni generiche del buffer di uno \textit{stream}, queste
vengono usate dalla funzione \func{setbuf}.  Non è detto però che tale
dimensione corrisponda sempre al valore ottimale (che può variare a seconda
del dispositivo).

Dato che la procedura di allocazione manuale è macchinosa, comporta dei
rischi, come delle scritture accidentali sul buffer, e non assicura la scelta
delle dimensioni ottimali, è sempre meglio lasciare allocare il buffer alle
funzioni di libreria, che sono in grado di farlo in maniera ottimale e
trasparente all'utente (in quanto la deallocazione avviene
automaticamente). Inoltre siccome alcune implementazioni usano parte del
buffer per mantenere delle informazioni di controllo, non è detto che le
dimensioni dello stesso coincidano con quelle su cui viene effettuato l'I/O.

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
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.

Oltre a \func{setvbuf} le \acr{glibc} definiscono altre tre funzioni per la
gestione della bufferizzazione di uno \textit{stream}: \funcd{setbuf},
\funcd{setbuffer} e \funcd{setlinebuf}, i rispettivi prototipi sono:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{void setbuf(FILE *stream, char *buf)}
\fdecl{void setbuffer(FILE *stream, char *buf, size\_t size)}
\fdesc{Impostano il buffer per uno \textit{stream}.} 
\fdecl{void setlinebuf(FILE *stream)}
\fdesc{Porta uno \textit{stream} in modalità \textit{line buffered}.}
}

{Le funzioni non ritornano niente e non hanno condizioni di errore.}  
\end{funcproto}


La funzione \func{setbuf} disabilita la bufferizzazione se \param{buf} è
\val{NULL}, altrimenti usa \param{buf} come buffer di dimensione
\const{BUFSIZ} in modalità \textit{fully buffered}, mentre \func{setbuffer}
disabilita la bufferizzazione se \param{buf} è \val{NULL}, altrimenti
usa \param{buf} come buffer di dimensione \param{size} in modalità
\textit{fully buffered}.  Tutte queste funzioni sono realizzate con opportune
chiamate a \func{setvbuf} e sono definite solo per compatibilità con le
vecchie librerie BSD, pertanto non è il caso di usarle se non per la
portabilità su vecchi sistemi.

Infine le \acr{glibc} provvedono le funzioni non standard, anche queste
originarie di Solaris, \funcd{\_\_flbf} e \funcd{\_\_fbufsize} che permettono
di leggere le proprietà di bufferizzazione di uno \textit{stream}; i cui
prototipi sono:

\begin{funcproto}{
\fhead{stdio\_ext.h}
\fdecl{size\_t \_\_fbufsize(FILE *stream)}
\fdesc{Restituisce le dimensioni del buffer di uno \textit{stream}.}
\fdecl{int \_\_flbf(FILE *stream)}
\fdesc{Controlla la modalità di bufferizzazione di uno \textit{stream}.}
}

{Le funzioni ritornano rispettivamente la dimensione del buffer o un valore
  non nullo se lo \textit{stream} è in modalità \textit{line-buffered}, non
  sono previste condizioni di errore.}
\end{funcproto}

Come già accennato, indipendentemente dalla modalità di bufferizzazione
scelta, si può forzare lo scarico dei dati sul file con la funzione
\funcd{fflush}, il cui prototipo è:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{int fflush(FILE *stream)}
\fdesc{Forza la scrittura dei dati bufferizzati di uno \textit{stream}.} 
}

{La funzione ritorna $0$ in caso di successo e \val{EOF} per un errore, nel
  qual caso \var{errno} assumerà il valore \errval{EBADF} se \param{stream}
  non è aperto o non è aperto in scrittura, o ad uno degli errori di
  \func{write}.}
\end{funcproto}

\noindent anche di questa funzione esiste una analoga \func{fflush\_unlocked}
(accessibile definendo \macro{\_BSD\_SOURCE} o \macro{\_SVID\_SOURCE} o
\macro{\_GNU\_SOURCE}) che non effettua il blocco dello \textit{stream}.

% TODO aggiungere prototipo \func{fflush\_unlocked}?

Se \param{stream} è \val{NULL} lo scarico dei dati è forzato per tutti gli
\textit{stream} aperti. Esistono però circostanze, ad esempio quando si vuole
essere sicuri che sia stato eseguito tutto l'output su terminale, in cui serve
poter effettuare lo scarico dei dati solo per gli \textit{stream} in modalità
\textit{line buffered}. Per fare questo le \acr{glibc} supportano una
estensione di Solaris, la funzione \funcd{\_flushlbf}, il cui prototipo è:

\begin{funcproto}{
\fhead{stdio-ext.h}
\fdecl{void \_flushlbf(void)}
\fdesc{Forza la scrittura dei dati bufferizzati degli \textit{stream} in
  modalità \textit{line buffered}.} 
}

{La funzione non ritorna nulla e non presenta condizioni di errore.}  
\end{funcproto}

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~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 è:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{int fpurge(FILE *stream)}
\fdesc{Cancella i buffer di uno \textit{stream}.} 
}

{La funzione ritorna $0$ in caso di successo e \val{EOF} per un errore.}  
\end{funcproto}

La funzione scarta tutti i dati non ancora scritti (se il file è aperto in
scrittura), e tutto l'input non ancora letto (se è aperto in lettura),
compresi gli eventuali caratteri rimandati indietro con \func{ungetc}.


\subsection{Gli \textit{stream} e i \textit{thread}}
\label{sec:file_stream_thread}

\itindbeg{thread}

Gli \textit{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
\textit{thread}, dato che l'implementazione delle librerie è influenzata
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 \textit{stream}
devono essere opportunamente protette, in quanto il sistema assicura
l'atomicità solo per le \textit{system call}. Questo viene fatto associando ad
ogni \textit{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
\textit{thread} necessita di compiere più di una operazione sullo
\textit{stream} atomicamente. Per questo motivo le librerie provvedono anche
le funzioni \funcd{flockfile} e \funcd{funlockfile} che permettono la gestione
esplicita dei blocchi sugli \textit{stream}. Esse sono disponibili definendo
\macro{\_POSIX\_THREAD\_SAFE\_FUNCTIONS} ed i loro prototipi sono:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{void flockfile(FILE *stream)}
\fdesc{Acquisisce il lock su uno \textit{stream}.} 
\fdecl{void funlockfile(FILE *stream)}
\fdesc{Rilascia  il lock su uno \textit{stream}.} 
}
{Le funzioni non ritornano nulla e non sono previste condizioni di errore.}  
\end{funcproto}

La funzione \func{flockfile} esegue l'acquisizione del lock dello
\textit{stream} \param{stream}, bloccandosi se questo risulta non è
disponibile, mentre \func{funlockfile} rilascia un lock che si è
precedentemente acquisito.

Una terza funzione, che serve a provare ad acquisire un lock senza bloccarsi
qualora non sia possibile, è \funcd{ftrylockfile}, il cui prototipo è:

\begin{funcproto}{
\fhead{stdio.h}
\fdecl{int ftrylockfile(FILE *stream)}
\fdesc{Tenta l'acquisizione del lock di uno \textit{stream}.} 
}

{La funzione ritorna $0$ in caso di acquisizione del lock ed un altro valore
  qualunque altrimenti, non sono previste condizioni di errore.}
\end{funcproto}

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 \textit{stream} non è necessario (come in
tutti i programmi che non usano i \textit{thread}), tutta la procedura può
comportare dei costi pesanti in termini di prestazioni. 

Per questo motivo abbiamo visto come alle usuali funzioni di I/O non
formattato siano associate delle versioni \code{\_unlocked} (alcune previste
dallo stesso standard POSIX, altre aggiunte come estensioni dalle \acr{glibc})
che possono essere usate quando il locking non serve\footnote{in certi casi
  dette funzioni possono essere usate, visto che sono molto più efficienti,
  anche in caso di necessità di locking, una volta che questo sia stato
  acquisito manualmente.}  con prestazioni molto più elevate, dato che spesso
queste versioni (come accade per \func{getc} e \func{putc}) sono realizzate
come macro.

La sostituzione di tutte le funzioni di I/O con le relative versioni
\code{\_unlocked} in un programma che non usa i \textit{thread} è però un
lavoro abbastanza noioso. Per questo motivo le \acr{glibc} forniscono al
programmatore pigro un'altra via, anche questa mutuata da estensioni
introdotte in Solaris, da poter utilizzare per disabilitare in blocco il
locking degli \textit{stream}: l'uso della funzione \funcd{\_\_fsetlocking},
il cui prototipo è:

\begin{funcproto}{
\fhead{stdio\_ext.h}
\fdecl{int \_\_fsetlocking(FILE *stream, int type)}
\fdesc{Specifica se abilitare il locking su uno \textit{stream}.}
}

{La funzione ritorna stato di locking interno dello \textit{stream}, non sono
  previste condizioni di errore.}  
\end{funcproto}

La funzione imposta o legge lo stato della modalità in cui le operazioni di
I/O su \param{stream} vengono effettuate rispetto all'acquisizione implicita
del locking a seconda del valore specificato con \param{type}, che può
assumere uno dei valori indicati in tab.~\ref{tab:file_fsetlocking_type}.

\begin{table}[htb]
  \centering
  \footnotesize
    \begin{tabular}[c]{|l|p{8cm}|}
      \hline
      \textbf{Valore} & \textbf{Significato} \\
      \hline
      \hline
      \const{FSETLOCKING\_INTERNAL}& Lo \textit{stream} userà da ora in poi il
                                     blocco implicito predefinito.\\
      \const{FSETLOCKING\_BYCALLER}& Al ritorno della funzione sarà l'utente a
                                     dover gestire da solo il locking dello
                                     \textit{stream}.\\
      \const{FSETLOCKING\_QUERY}   & Restituisce lo stato corrente della
                                     modalità di blocco dello
                                     \textit{stream}.\\
      \hline
    \end{tabular}
    \caption{Valori dell'argomento \param{type} di \func{\_\_fsetlocking} 
      per l'impostazione delle modalità di bufferizzazione.}
  \label{tab:file_fsetlocking_type}
\end{table}

La funzione, se usata con \const{FSETLOCKING\_QUERY}, non modifica la modalità
di operazione ma restituisce lo stato di locking interno dello \textit{stream}
con uno dei valori \const{FSETLOCKING\_INTERNAL} o
\const{FSETLOCKING\_BYCALLER}.

% TODO trattare \func{clearerr\_unlocked} 

\itindend{thread}



%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "gapil"
%%% End: 

% LocalWords:  stream cap system call kernel Ritchie glibc descriptor Stevens
% LocalWords:  buf read write filesystem st blksize stat sez l'header stdio BSD
% LocalWords:  nell'header stdin shell stdout stderr error freopen flush line
% LocalWords:  unbuffered buffered newline fully SVr fopen fdopen POSIX const
% LocalWords:  char path int fildes NULL errno malloc fcntl fclose fflush tab
% LocalWords:  dup fifo socket append EXCL ccs IRUSR IWUSR IRGRP IWGRP inode fd
% LocalWords:  IROTH IWOTH umask fseek fsetpos rewind SEEK CUR EOF EBADF close
% LocalWords:  sync fcloseall void stdlib of feof ferror clearerr ws VFS table
% LocalWords:  unlocked fread fwrite size ptr nmemb nelem gcc padding point str
% LocalWords:  lock thread fgetc getc getchar dell'overhead unsigned ap process
% LocalWords:  getwc fgetwc getwchar wint wchar WEOF putc fputc putchar  struct
% LocalWords:  SVID getw putw parsing peeking ahead ungetc gets fgets string Di
% LocalWords:  overflow Aleph stack fputs puts fgetws fputws getline ssize leak
% LocalWords:  realloc value result argument memory getdelim delim printf short
% LocalWords:  fprintf sprintf format snprintf variadic long double intmax list
% LocalWords:  uintmax ptrdiff vprintf vfprintf vsprintf vsnprintf asprintf lex
% LocalWords:  vasprintf strptr dprintf vdprintf print scanf fscanf sscanf flex
% LocalWords:  vscanf vfscanf vsscanf bison parser yacc like off VMS whence pos
% LocalWords:  lseek ftell fgetpos fpos fseeko ftello fileno Solaris freadable
% LocalWords:  fwritable ext freading fwriting buffering setvbuf BUFSIZ setbuf
% LocalWords:  IONBF IOLBF IOFBF setbuffer setlinebuf flbf fbufsize flushlbf hh
% LocalWords:  fsync fpurge flockfile ftrylockfile funlockfile  files fig flags
% LocalWords:  locking fsetlocking type virtual operation dentry unistd sys AT
% LocalWords:  modification hole functions pathname EEXIST CREAT EINTR attack
% LocalWords:  EISDIR EFBIG EOVERFLOW ELOOP NOFOLLOW ENODEV ENOENT ENOTDIR fork
% LocalWords:  EMFILE ENAMETOOLONG ENFILE ENOMEM ENOSPC EROFS exec access RDWR
% LocalWords:  RDONLY ioctl AND ACCMODE creation Denial Service DoS opendir NFS
% LocalWords:  SOURCE LARGEFILE BITS NOCTTY TRUNC SHLOCK shared EXLOCK race SGI
% LocalWords:  exclusive condition change ASYNC SIGIO CLOEXEC DIRECT NDELAY EIO
% LocalWords:  DSYNC FASYNC IRIX FreeBSD EINVAL client RSYNC creat filedes INCR
% LocalWords:  behind shutdown ESPIPE XTND truncate fallocate count EAGAIN log
% LocalWords:  timerfd Specification pwrite pread define XOPEN EPIPE SIGPIPE at
% LocalWords:  caching cache update bdflush fdatasync fstat oldfd newfd DUPFD
% LocalWords:  openat mkdirat mkdir proc ATFILE dirfd FDCWD utimes lutimes uid
% LocalWords:  utimensat faccessat fchmodat chmod fchownat chown lchown fstatat
% LocalWords:  lstat linkat mknodat mknod readlinkat readlink renameat rename
% LocalWords:  symlinkat symlink unlinkat unlink rmdir mkfifoat mkfifo owner is
% LocalWords:  gid group FOLLOW REMOVEDIR cmd arg flock SETFD GETFD GETFL SETFL
% LocalWords:  GETLK SETLK SETLKW GETOWN PID Signal SIGURG SETOWN GETSIG SETSIG
% LocalWords:  sigaction SIGINFO siginfo SETLEASE lease GETLEASE NOTIFY request
% LocalWords:  everything framebuffer ENOTTY argp CDROM lsattr chattr magic TID
% LocalWords:  number FIOCLEX FIONCLEX FIOASYNC FIONBIO FIOSETOWN FIOGETOWN pid
% LocalWords:  FIONREAD epoll FIOQSIZE side effects SAFE BYCALLER QUERY EACCES
% LocalWords:  EBUSY OpenBSD syncfs futimes timespec only init ESRCH kill NTPL
% LocalWords:  ENXIO  NONBLOCK WRONLY EPERM NOATIME ETXTBSY EWOULDBLOCK PGRP SZ
% LocalWords:  EFAULT capabilities GETPIPE SETPIPE RESOURCE

%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "gapil"
%%% End: 
