From c38de228492fae73086d8dfcf89b70c03b880055 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Sun, 7 Apr 2019 18:20:15 +0200 Subject: [PATCH] Trattazione di renameat2 --- fileio.tex | 206 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 165 insertions(+), 41 deletions(-) diff --git a/fileio.tex b/fileio.tex index 975a9c1..b6a0dcd 100644 --- a/fileio.tex +++ b/fileio.tex @@ -1971,9 +1971,9 @@ pag.~\pageref{open_o_path_flag}). Quando si usa questo flag \param{pathname} 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} @@ -2002,9 +2002,9 @@ un eventuale collegamento simbolico, facendo comportare \func{fchownat} come 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} @@ -2032,10 +2032,10 @@ indicare alla funzione di eseguire il controllo dei permessi con l'\ids{UID} \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} @@ -2067,17 +2067,18 @@ valori (la funzione non segue comunque i collegamenti simbolici e 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} @@ -2126,8 +2127,8 @@ sempre usato il comportamento che per altre funzioni deve essere attivato con 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} @@ -2156,13 +2157,10 @@ di \param{flags} consente di farla comportare come \func{lstat} se si usa 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} @@ -2177,35 +2175,161 @@ prototipo è: \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} +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} con il significato illustrato in precedenza. + +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} -Un'altra funzione che +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. + +\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://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/ +% 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 -- 2.30.2