%% fileio.tex (merge fileunix.tex - filestd.tex)
%%
-%% Copyright (C) 2000-2018 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2019 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",
deve essere vuoto, da cui il nome della costante, ed in tal caso la funzione
agirà direttamente sul file associato al file descriptor \param{dirfd}.
-Una prima funzione che utilizza l'argomento \param{flag} è \funcd{fchownat},
-che può essere usata per sostituire sia \func{chown} che \func{lchown}; il suo
-prototipo è:
+Una prima funzione di sistema che utilizza l'argomento \param{flag} è
+\funcd{fchownat}, che può essere usata per sostituire sia \func{chown} che
+\func{lchown}; il suo prototipo è:
\begin{funcproto}{
\fhead{fcntl.h}
di \const{AT\_EMPTY\_PATH}, con il significato illustrato in precedenza e non
ha flag specifici.
-Una seconda funzione che utilizza l'argomento \param{flags}, in questo caso
-anche per modificare il suo comportamento, è \funcd{faccessat}, ed il suo
-prototipo è:
+Una seconda funzione di sistema che utilizza l'argomento \param{flags}, in
+questo caso anche per modificare il suo comportamento, è \funcd{faccessat}, ed
+il suo prototipo è:
\begin{funcproto}{
\fhead{fcntl.h}
\textsl{effettivo} invece di quello \textsl{reale}. L'unico altro valore
consentito è \const{AT\_SYMLINK\_NOFOLLOW}, con il significato già spiegato.
-Un'altra funzione che ha un utilizzo specifico dell'argomento \param{flags} è
-\funcd{unlinkat}, in questo caso l'argomento 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 è:
+Un utilizzo specifico dell'argomento \param{flags} viene fatto anche dalla
+funzione di sistema \funcd{unlinkat}, in questo caso l'argomento 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}
maschera binaria, essendo \const{AT\_REMOVEDIR} l'unico flag disponibile per
questa funzione, lo si può assegnare direttamente.
-Un'altra funzione che usa l'argomento \param{flags} è \func{utimensat}, che
-però non è una corrispondente esatta delle funzioni classiche \func{utimes} e
-\func{lutimes}, in quanto ha una maggiore precisione nella indicazione dei
-tempi dei file, per i quali, come per \func{futimens}, si devono usare
-strutture \struct{timespec} che consentono una precisione fino al nanosecondo;
-la funzione è stata introdotta con il kernel 2.6.22,\footnote{in precedenza, a
- partire dal kernel 2.6.16, era stata introdotta una \textit{system call}
- \funcm{futimesat} seguendo una bozza della revisione dello standard poi
- modificata; questa funzione, sostituita da \func{utimensat}, è stata
- dichiarata obsoleta, non è supportata da nessuno standard e non deve essere
- più utilizzata: pertanto non ne parleremo.} ed il suo prototipo è:
+Un'altra funzione di sistema che usa l'argomento \param{flags} è
+\func{utimensat}, che però non è una corrispondente esatta delle funzioni
+classiche \func{utimes} e \func{lutimes}, in quanto ha una maggiore precisione
+nella indicazione dei tempi dei file, per i quali, come per \func{futimens},
+si devono usare strutture \struct{timespec} che consentono una precisione fino
+al nanosecondo; la funzione è stata introdotta con il kernel
+2.6.22,\footnote{in precedenza, a partire dal kernel 2.6.16, era stata
+ introdotta una \textit{system call} \funcm{futimesat} seguendo una bozza
+ della revisione dello standard poi modificata; questa funzione, sostituita
+ da \func{utimensat}, è stata dichiarata obsoleta, non è supportata da
+ nessuno standard e non deve essere più utilizzata: pertanto non ne
+ parleremo.} ed il suo prototipo è:
\begin{funcproto}{
\fhead{fcntl.h}
disabilitato, e la funzione, seguendo lo standard POSIX, ritorna un errore di
\errval{EINVAL} se invocata in questo modo.
-Come analoga delle funzioni \func{stat}, \func{fstat} e \func{lstat} si può
-utilizzare invece \funcd{fstatat}, il cui prototipo è:
+Come corrispondente di \func{stat}, \func{fstat} e \func{lstat} si può
+utilizzare invece la funzione di sistema \funcd{fstatat}, il cui prototipo è:
\begin{funcproto}{
\fhead{fcntl.h}
però supportato l'ulteriore valore \const{AT\_NO\_AUTOMOUNT} che qualora
\param{pathname} faccia riferimento ad una directory marcata per
l'\textit{automount} ne evita il montaggio automatico.
-
-
-Ancora diverso è il caso di \funcd{linkat},\footnote{si tenga presente che per
- questa funzione l'argomento \param{flags} è disponibile ed utilizzabile solo
- a partire dal kernel 2.6.18.} anche se in questo caso l'utilizzo continua ad
-essere attinente al comportamento con i collegamenti simbolici, il suo
-prototipo è:
+
+Ancora diverso è il caso di \funcd{linkat} anche se in questo caso l'utilizzo
+continua ad essere attinente al comportamento con i collegamenti simbolici, il
+suo prototipo è:
\begin{funcproto}{
\fhead{fcntl.h}
\item[\errcode{EBADF}] \param{olddirfd} o \param{newdirfd} non sono un file
descriptor valido.
\item[\errcode{EINVAL}] \param{flags} non ha un valore valido.
- \item[\errcode{ENOTDIR}] \param{oldpath} e \param{newpath} è un
- \textit{pathname} relativo, ma \param{oldirfd} o \param{newdirfd} fa
+ \item[\errcode{ENOTDIR}] \param{oldpath} e \param{newpath} sono
+ \textit{pathname} relativi, ma \param{oldirfd} o \param{newdirfd} fa
riferimento ad un file.
\end{errlist}
}
\end{funcproto}
-In questo caso dato che su Linux il comportamento di \func{link} è quello di
+Anche in questo caso la funzione è sostanzialmente identica alla classica
+\func{link}, ma dovendo specificare due \textit{pathname} (sorgente e
+destinazione) aggiunge a ciascuno di essi un argomento (rispettivamente
+\param{olddirfd} e \param{newdirfd}) per poter indicare entrambi come relativi
+a due directory aperte in precedenza.
+
+In questo caso, dato che su Linux il comportamento di \func{link} è quello di
non seguire mai i collegamenti simbolici, \const{AT\_SYMLINK\_NOFOLLOW} non
-viene utilizzato, mentre si può usare \const{AT\_EMPTY\_PATH} con il
-significato illustrato in precedenza. A partire dal kernel 2.6.18 è è stato
-inoltre aggiunto per questa funzione la possibilità di usare il valore
-\const{AT\_SYMLINK\_FOLLOW}, che richiede di dereferenziare i collegamenti
-simbolici.
+viene utilizzato. A partire dal kernel 2.6.18 è stato aggiunto a questa
+funzione la possibilità di usare il valore \const{AT\_SYMLINK\_FOLLOW} per
+l'argomento \param{flags},\footnote{nei kernel precendenti, dall'introduzione
+ nel 2.6.16, l'argomento \param{flags} era presente, ma senza alcun valore
+ valido, e doveva essere passato sempre con valore nullo.} che richiede di
+dereferenziare i collegamenti simbolici. Inoltre a partire dal kernel 3.11 si
+può usare \const{AT\_EMPTY\_PATH} per creare un nuovo \textit{hard link} al
+file associato al file descriptor \param{olddirfd}.
+% NOTE per la discussione sui problemi di sicurezza relativi a questa
+% funzionalità vedi http://lwn.net/Articles/562488/
-Un'altra funzione che
+La funzione prevede inoltre un comportamento specifico nel caso che
+\param{olddirfd} faccia riferimento ad un file anonimo ottenuto usando
+\func{open} con \const{O\_TMPFILE}. In generale quando il file associato ad
+\param{olddirfd} ha un numero di link nullo (come in questo caso), la funzione
+fallisce, c'è però una
+
+
+l'uso di \const{AT\_EMPTY\_PATH} assume un significato
+ulteriore, e richiede i privilegi di amministratore (la \textit{capability}
+\const{CAP\_DAC\_READ\_SEARCH}) quando viene usato con un file descriptor
+anomino ottenuto usando \const{O\_TMPFILE} con \func{open}. In generale
+
+
+Altre due funzioni che utilizzano due \textit{pathname} (e due file
+descriptor) sono \funcd{renameat} e \funcd{renameat2}, corrispondenti alla
+classica \func{rename}; i rispettivi prototipi sono:
+
+\begin{funcproto}{
+\fhead{fcntl.h}
+\fdecl{int renameat(int olddirfd, const char *oldpath, int newdirfd, const
+ char *newpath)}
+\fdecl{int renameat2(int olddirfd, const char *oldpath, int newdirfd, \\
+\phantom{int renameat2(}const char *newpath, int flags)}
+\fdesc{Rinomina o sposta un file o una directory.}
+}
+
+{La funzioni ritornano gli stessi valori e gli stessi codici di errore di
+ \func{rename}, ed in più per entrambe:
+ \begin{errlist}
+ \item[\errcode{EBADF}] \param{olddirfd} o \param{newdirfd} non sono un file
+ descriptor valido.
+ \item[\errcode{ENOTDIR}] \param{oldpath} e \param{newpath} sono
+ \textit{pathname} relativi, ma i corrispondenti \param{oldirfd} o
+ \param{newdirfd} fan riferimento ad un file e non a una directory.
+ \end{errlist}
+ e per \func{renameat2} anche:
+ \begin{errlist}
+ \item[\errcode{EEXIST}] si è richiesto \macro{RENAME\_NOREPLACE} ma
+ \param{newpath} esiste già.
+ \item[\errcode{EINVAL}] Si è usato un flag non valido in \param{flags}, o si
+ sono usati insieme a \macro{RENAME\_EXCHANGE} o \macro{RENAME\_NOREPLACE}
+ o \macro{RENAME\_WHITEOUT}, o non c'è il supporto nel filesystem per una
+ delle operazioni richieste in \param{flags}.
+ \item[\errcode{ENOENT}] si è richiesto \macro{RENAME\_EXCHANGE} e
+ \param{newpath} non esiste.
+ \item[\errcode{EPERM}] si è richiesto \macro{RENAME\_WHITEOUT} ma il
+ chiamante non ha i privilegi di amministratore.
+ \end{errlist}
+}
+\end{funcproto}
+
+In realtà la corrispondente di \func{rename}, prevista dallo standard
+POSIX.1-2008 e disponibile dal kernel 2.6.16 come le altre
+\textit{at-functions}, sarebbe soltanti \func{renameat}, su Linux però, a
+partire dal kernel dal 3.15, questa è stata realizzata in termini della nuova
+funzione di sistema \func{renameat2} che prevede l'uso dell'argomento
+aggiuntivo \param{flags}; in questo caso \func{renameat} è totalmente
+equivalente all'utilizzo di \func{renamat2} con un valore nullo per
+\param{flags}.
+
+L'uso di \func{renameat} è identico a quello di \func{rename}, con le solite
+note relativie alle estensioni delle \textit{at-functions}, applicate ad
+entrambi i \textit{pathname} passati come argomenti alla funzione. Con
+\func{renameat2} l'introduzione dell'argomento \func{flags} (i cui valori
+possibili sono riportati in tab.~\ref{tab:renameat2_flag_values}) ha permesso
+di aggiungere alcune funzionalità non previste al momento da nessuno standard,
+e specifiche di Linux. Si tenga conto che questa funzione di sistema non viene
+definita nella \acr{glibc} per cui deve essere chiamata utilizzando
+\func{syscall} come illustrato in sez.~\ref{sec:intro_syscall}.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{8cm}|}
+ \hline
+ \textbf{Costante} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{RENAME\_EXCHANGE} & richiede uno scambio di nomi fra
+ \param{oldpath} e \param{newpath}, non è
+ usabile con \const{RENAME\_NOREPLACE}.\\
+ \const{RENAME\_NOREPLACE}& non sovrascrive \param{newpath} se questo
+ esiste dando un errore.\\
+ \const{RENAME\_WHITEOUT} & crea un oggetto di \textit{whiteout}
+ contestualmente al cambio di nome
+ (disponibile a partire dal kernel 3.18).\\
+ \hline
+ \end{tabular}
+ \caption{I valori specifici dei bit dell'argomento \param{flags} per l'uso
+ con \func{renameat2}.}
+ \label{tab:renameat2_flag_values}
+\end{table}
+
+L'uso dell'argomento \param{flags} in questo caso non attiene alle
+funzionalità relative alla \textit{at-functions}, ma consente di estendere le
+funzionalità di \func{rename}. In particolare \func{renameat2} consente di
+eseguire uno scambio di nomi in maniera atomica usando il flag
+\constd{RENAME\_EXCHANGE}; quando viene specificato la funzione non solo
+rinomina \param{oldpath} in \param{newpath}, ma rinomina anche, senza dover
+effettuare un passaggio intermedio, \param{newpath} in \param{oldpath}. Quando
+si usa questo flag, entrambi i \textit{pathname} passati come argomenti alla
+funzione devono esistere, e non è possibile usare \const{RENAME\_NOREPLACE},
+non ci sono infine restrizioni sul tipo dei file (regolari, directory, link
+simbolici, ecc.) di cui si scambia il nome.
+
+Il flag \constd{RENAME\_NOREPLACE} consente di richiedere la generazione di un
+errore nei casi in cui \func{rename} avrebbe causato una sovrascrittura della
+destinazione, rendendo possibile evitare la stessa in maniera atomica; un
+controllo preventivo dell'esistenza del file infatti avrebbe aperto alla
+possibilità di una \textit{race condition} fra il momento del controllo e
+quella del cambio di nome.
+
+\itindbeg{overlay~filesytem}
+\itindbeg{union~filesytem}
+
+Infine il flag \constd{RENAME\_WHITEOUT}, introdotto con il kernel 3.18,
+richiede un approfomdimento specifico, in quanto attiene all'uso della
+funzione con dei filesystem di tipo \textit{overlay}/\textit{union}, dato che
+il flag ha senso solo quando applicato a file che stanno su questo tipo di
+filesystem.
+
+Un \textit{overlay} o \texttt{union filesystem} è un filesystem speciale
+strutturato in livelli, in cui si rende scrivibile un filesystem accessibile
+in sola lettura, \textsl{sovrapponendogli} un filesystem scrivibile su cui
+vanno tutte le modifiche. Un tale tipo di filesystem serve ad esempio a
+rendere scrivibili i dati processati quando si fa partire una distribuzione
+\textit{Live} basata su CD o DVD, ad esempio usando una chiavetta o uno spazio
+disco aggiuntivo.
+
+In questo caso quando si rinomina un file che sta nello strato in sola lettura
+quello che succede è questo viene copiato a destinazione sulla parte
+accessibile in scrittura, ma l'originale non può essere cancellato, per far si
+che esso non appaia più è possibile creare
+
+\itindend{overlay~filesytem}
+\itindend{union~filesytem}
-% TODO trattare fstatat e con essa
% TODO trattare anche statx, aggiunta con il kernel 4.11 (vedi
% https://lwn.net/Articles/707602/ e
% https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a528d35e8bfcc521d7cb70aaf03e1bd296c8493f)
-% 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: Trattare esempio di inzializzazione di file e successivo collegamento
% con l'uso di O_TMPFILE e linkat, vedi man open
% TODO: mettere prototipi espliciti fseeko e ftello o menzione?
-
\subsection{Input/output binario}
\label{sec:file_binary_io}