Integrazioni su write
[gapil.git] / fileio.tex
index acbedc27d3b7796663f76093366286280f7d25b3..7b326993c04038bb18fab5dea3c210530d45183e 100644 (file)
@@ -258,7 +258,7 @@ corrispondente,\footnote{è \func{open} che alloca \kstruct{file}, la inserisce
     supporta la funzionalità.
   \item[\errcode{EFBIG}] il file è troppo grande per essere aperto, in genere
     dovuto al fatto che si è compilata una applicazione a 32 bit senza
-    abilitare il supporto per le dimesioni a 64 bit; questo è il valore
+    abilitare il supporto per le dimensioni a 64 bit; questo è il valore
     restituito fino al kernel 2.6.23, coi successivi viene restituito
     \errcode{EOVERFLOW} come richiesto da POSIX.1.
   \item[\errcode{ELOOP}] si sono incontrati troppi collegamenti simbolici nel
@@ -451,6 +451,11 @@ sez.~\ref{sec:file_fcntl_ioctl}).
                             aggiunta in Linux a partire dal kernel
                             2.1.126, ed utilizzabile soltanto se si è definita
                             la macro \macro{\_GNU\_SOURCE}.\\
+      \const{O\_TMPFILE} & Consente di creare un file temporaneo anonimo, non
+                           visibile con un pathname sul filesystem, ma
+                           leggibile e scrivibile all'interno del processo.
+                           Introdotto con il kernel 3.11, è specifico di
+                           Linux.\\ 
       \constd{O\_TRUNC}  & Se usato su un file di dati aperto in scrittura,
                            ne tronca la lunghezza a zero; con un terminale o
                            una \textit{fifo} viene ignorato, negli altri casi
@@ -471,7 +476,7 @@ 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 \constd{O\_SHLOCK}, che aprirebbe il file con uno \textit{shared lock}
   e \constd{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
+  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
@@ -481,7 +486,7 @@ 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 un
 file di lock potrebbe dar luogo a una \textit{race condition}, in tal caso
-infatto un file potrebbe venir creato fra il controllo la successiva apertura
+infatti 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 file di lock,
 (vedi sez.~\ref{sec:ipc_file_lock}).
@@ -505,6 +510,55 @@ 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}.
 
+Il flag \constd{O\_TMPFILE}, introdotto con il kernel
+3.11,\footnote{inizialmente solo su alcuni filesystem (i vari \acr{extN},
+  \acr{Minix}, \acr{UDF}, \acr{shmem}) poi progressivamente esteso ad altri
+  (\acr{XFS} con il 3.15, \acr{Btrfs} e \acr{F2FS} con il 3.16, \acr{ubifs}
+  con il 4.9).}  consente di aprire un file temporaneo senza che questo venga
+associato ad un nome e compaia nel filesystem. In questo caso la funzione
+restituirà un file descriptor da poter utilizzare per leggere e scrivere dati,
+ma il contenuto dell'argomento \param{path} verrà usato solamente per
+determinare, in base alla directory su cui si verrebbe a trovare il
+\textit{pathname} indicato, il filesystem all'interno del quale deve essere
+allocato l'\textit{inode} e lo spazio disco usato dal file
+descriptor. L'\textit{inode} resterà anonimo e l'unico riferimento esistente
+sarà quello contenuto nella \textit{file table} del processo che ha chiamato
+\func{open}.
+
+Lo scopo principale del flag è quello fornire una modalità atomica, semplice e
+sicura per applicare la tecnica della creazione di un file temporaneo seguita
+dalla sua immediata cancellazione con \func{unlink} per non lasciare rimasugli
+sul filesystem, di cui è parlato in sez.~\ref{sec:link_symlink_rename}.
+Inoltre, dato che il file non compare nel filesystem, si evitano alla radice
+tutti gli eventuali problemi di \textit{race condition} o \textit{symlink
+  attack} e non ci si deve neanche preoccupare di ottenere un opportuno nome
+univoco con l'uso delle funzioni di sez.~\ref{sec:file_temp_file}.
+
+Una volta aperto il file vi si potrà leggere o scrivere a seconda che siano
+utilizzati \const{O\_RDWR} o \const{O\_WRONLY}, mentre l'uso di
+\func{O\_RDONLY} non è consentito, non avendo molto senso ottenere un file
+descriptor su un file che nasce vuoto per cui non si potrà comunque leggere
+nulla. L'unico altro flag che può essere utilizzato insieme a
+\const{O\_TMPFILE} è \const{O\_EXCL}, che in questo caso assume però un
+significato diverso da quello ordinario, dato che in questo caso il file
+associato al file descriptor non esiste comunque.
+
+L'uso di \const{O\_EXCL} attiene infatti all'altro possibile impiego di
+\const{O\_TMPFILE} oltre a quello citato della creazione sicura di un file
+temporaneo come sostituto sicuro di \func{tmpfile}: la possibilità di creare
+un contenuto iniziale per un file ed impostarne permessi, proprietario e
+attributi estesi con \func{fchmod}, \func{fchown} e \func{fsetxattr}, senza
+possibilità di \textit{race condition} ed interferenze esterne, per poi far
+apparire il tutto sul filesystem in un secondo tempo utilizzando \func{linkat}
+sul file descriptor (torneremo su questo in sez.~\ref{sec:file_openat}) per
+dargli un nome. Questa operazione però non sarà possibile se si è usato
+\const{O\_EXCL}, che in questo caso viene ad assumere il significato di
+escludere la possibilità di far esistere il file anche in un secondo tempo.
+
+% NOTE: per O_TMPFILE vedi: http://kernelnewbies.org/Linux_3.11
+% https://lwn.net/Articles/558598/ http://lwn.net/Articles/619146/
+
+
 \begin{table}[!htb]
   \centering
   \footnotesize
@@ -542,7 +596,7 @@ si tronca il file con \const{O\_TRUNC} verranno impostati soltanto il
                            l'impostazione della suddetta modalità con
                            \func{fcntl} (vedi
                            sez.~\ref{sec:file_fcntl_ioctl}).\\ 
-      \constd{O\_DIRECT} & Esegue l'I/O direttamente dalla memoria in
+      \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
@@ -592,11 +646,6 @@ si tronca il file con \const{O\_TRUNC} verranno impostati soltanto il
                            dell'arrivo degli stessi e della parte di metadati
                            ad essi relativa sull'hardware sottostante (in
                            questo significato solo dal kernel 2.6.33).\\
-      \const{O\_TMPFILE} & Consente di creare un file temporaneo anonimo, non
-                           visibile con un pathname sul filesystem, ma
-                           leggibile e scrivibile all'iterno del processo.
-                           Introdotto con il kernel 3.11, è specifico di
-                           Linux.\\ 
       \hline
     \end{tabular}
     \caption{Le costanti che identificano le \textit{modalità di operazione} di
@@ -628,7 +677,7 @@ 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 è
+Il flag \constd{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
@@ -656,7 +705,7 @@ 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
+  causare problemi di prestazioni.} Per questo in genere 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
@@ -697,7 +746,6 @@ all'identificazione di una posizione sul filesystem (ad uso delle
 operazioni che riguardano il file descriptor in quanto tale, senza consentire
 operazioni sul file; in sostanza se si apre un file con \const{O\_PATH} si
 potrà soltanto:
-
 \begin{itemize*}
 \item usare il file descriptor come indicatore della directory di partenza con
   una delle \textit{at-functions} (vedi sez.~\ref{sec:file_openat});
@@ -714,24 +762,34 @@ potrà soltanto:
     flags} con \func{fcntl} (rispettivamente con le operazioni
   \const{F\_GETFL}, \const{F\_SETFD} e \const{F\_GETFD}, vedi
   sez.~\ref{sec:file_fcntl_ioctl}).
-\item chiudere il file con \func{close};
+\item chiudere il file con \func{close}.
 \end{itemize*}
 
-In realtà usando \const{O\_PATH} il file non viene effettivamente aperto per
+In realtà usando \const{O\_PATH} il file non viene effettivamente aperto, per
 cui ogni tentativo di usare il file descriptor così ottenuto con funzioni che
 operano effettivamente sul file (come ad esempio \func{read}, \func{write},
-\func{fchown}, \func{fchmod}, \func{ioctl}, ecc.) fallirano con un errore di
-\errval{EBADF}, come se questo non fosse un file descriptor valido.
+\func{fchown}, \func{fchmod}, \func{ioctl}, ecc.) fallirà con un errore di
+\errval{EBADF}, come se questo non fosse un file descriptor valido. Per questo
+motivo usando questo flag non è necessario avere nessun permesso per aprire un
+file, neanche quello di lettura (occorre ovviamente avere il permesso di
+esecuzione per le directory sovrastanti).
+
+Questo consente di usare il file descriptor con funzioni che non richiedono
+permessi sul file, come \func{fstat}, laddove un'apertura con
+\const{O\_RDONLY} sarebbe fallita. I permessi verranno eventualmente
+controllati, se necessario, nelle operazioni seguenti, ad esempio per usare
+\func{fchdir} con il file descriptor (se questo fa riferimento ad una
+directory) occorrerà avere il permesso di esecuzione.
 
 Se si usa \const{O\_PATH} tutti gli altri flag eccettuati \const{O\_CLOEXEC},
-\const{O\_DIRECTORY} e \const{O\_NOFOLLOW} verranno ignorati.
-
-% 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/ http://lwn.net/Articles/619146/
-
-
+\const{O\_DIRECTORY} e \const{O\_NOFOLLOW} verranno ignorati. I primi due
+mantengono il loro significato usuale, mentre \const{O\_NOFOLLOW} fa si che se
+il file indicato è un un link simbolico venga aperto quest'ultimo (cambiando
+quindi il comportamento ordinario che prova il fallimento della chiamata),
+così da poter usare il file descriptor ottenuto per le funzioni
+\func{fchownat}, \func{fstatat}, \func{linkat} e \func{readlinkat} che ne
+supportano l'uso come come primo argomento (torneremo su questo in
+sez.~\ref{sec:file_openat}).
 
 
 Nelle prime versioni di Unix i valori di \param{flag} specificabili per
@@ -789,24 +847,32 @@ 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.}
+infatti implementano la tecnica del cosiddetto \itindex{write-behind}
+\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.
-
+\func{sync} (vedi sez.~\ref{sec:file_sync}) effettua esplicitamente lo scarico
+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.
+
+Si tenga comunque presente che ripetere la chiusura in caso di fallimento non
+è opportuno, una volta chiamata \func{close} il file descriptor viene comunque
+rilasciato, indipendentemente dalla presenza di errori, e se la riesecuzione
+non comporta teoricamente problemi (se non la sua inutilità) se fatta
+all'interno di un processo singolo, nel caso si usino i \textit{thread} si
+potrebbe chiudere un file descriptor aperto nel contempo da un altro
+\textit{thread}.
 
 \subsection{La gestione della posizione nel file}
 \label{sec:file_lseek}
@@ -980,11 +1046,11 @@ 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
-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
+buco in un file è lasciata all'implementazione del filesystem, dato che oltre
+a quelle classiche appena esposte 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}). 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}).
@@ -1107,8 +1173,8 @@ 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.
+(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
@@ -1139,6 +1205,10 @@ prototipo è:
   \begin{errlist}
   \item[\errcode{EAGAIN}] ci si sarebbe bloccati, ma il file era aperto in
     modalità \const{O\_NONBLOCK}.
+  \item[\errcode{EDESTADDRREQ}] si è eseguita una scrittura su un socket di
+    tipo \textit{datagram} (vedi sez.~\ref{sec:sock_type}) senza aver prima
+    connesso il corrispondente con \func{connect} (vedi
+    sez.~\ref{sec:UDP_sendto_recvfrom}).
   \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.
@@ -1146,13 +1216,14 @@ prototipo è:
     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{EPERM}] la scrittura è proibita da un \textit{file seal}.
   \item[\errcode{EPIPE}] \param{fd} è connesso ad una \textit{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.}
+  ed inoltre \errval{EBADF}, \errval{EDQUOT}, \errval{EFAULT}, \errval{EIO},
+  \errval{EISDIR}, \errval{ENOSPC} nel loro significato generico.}
 \end{funcproto}
 
 
@@ -1774,7 +1845,12 @@ 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/ 
+% http://lwn.net/Articles/562488/
+
+% TODO: Trattare esempio di inzializzazione di file e successivo collegamento
+% con l'uso di O_TMPFILE e linkat, vedi man open
+
+
 % TODO manca prototipo di utimensat, verificare se metterlo o metter menzione
 % TODO manca prototipo di renameat2, introdotta nel 3.15, vedi
 % http://lwn.net/Articles/569134/ 
@@ -4406,5 +4482,8 @@ con uno dei valori \const{FSETLOCKING\_INTERNAL} o
 %%% mode: latex
 %%% TeX-master: "gapil"
 %%% End: 
-%  LocalWords:  l'I nell' du vm Documentation Urlich Drepper futimesat times
-%  LocalWords:  futimens fs Tread all'I ll
+
+% LocalWords:  nell' du vm Documentation Urlich Drepper futimesat times
+%  LocalWords:  futimens fs Tread all'I ll TMPFILE EDQUOT extN Minix UDF XFS
+%  LocalWords:  shmem Btrfs ubifs tmpfile fchmod fchown fsetxattr fchdir PF
+%  LocalWords:  fstatfs sull'