X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileio.tex;h=94ac81d85e58638e9718a224be8b2114b2dfb22b;hp=e6a904f1cced90f6b42c354db6b11b22f053b0fe;hb=be93b54a4875d772cce5cbff77d32241039d0367;hpb=aeebfb3d7a3482d1255aeb318d01bbdd92829f4c diff --git a/fileio.tex b/fileio.tex index e6a904f..94ac81d 100644 --- a/fileio.tex +++ b/fileio.tex @@ -739,13 +739,13 @@ 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/ -Il flag \constd{O\_PATH}, introdotto con il kernel 2.6.39, viene usato per -limitare l'uso del file descriptor restituito da \func{open} o -all'identificazione di una posizione sul filesystem (ad uso delle -\textit{at-functions} che tratteremo in sez.~\ref{sec:file_openat}) o alle -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: +Il flag \constd{O\_PATH},\label{open_o_path_flag} introdotto con il kernel +2.6.39, viene usato per limitare l'uso del file descriptor restituito da +\func{open} o all'identificazione di una posizione sul filesystem (ad uso +delle \textit{at-functions} che tratteremo in sez.~\ref{sec:file_openat}) o +alle 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}); @@ -1722,7 +1722,7 @@ descriptor su cui si sta operando, e la registrazione immediata dei dati sarà limitata al filesystem su cui il file ad esso corrispondente si trova. -\subsection{Le \textit{at-functions}: \func{openat} e compagnia} +\subsection{Le \textit{at-functions}: \func{openat} e le altre} \label{sec:file_openat} \itindbeg{at-functions} @@ -1740,19 +1740,18 @@ successiva apertura. Inoltre, come già accennato, la directory di lavoro corrente è una proprietà associata al singolo processo; questo significa che quando si lavora con i -\textit{thread} questa sarà sempre la stessa per tutti \textit{thread}, ed un -cambiamento di directory di lavoro effettuato all'interno di un \textit{thread} -verrà applicato a tutti gli altri. Non esiste quindi con le funzioni classiche -un modo semplice per far si che i singoli \textit{thread} possano aprire file -usando una propria directory di lavoro per risolvere i \textit{pathname} -relativi. +\textit{thread} questa è la stessa per tutti, per cui se la si cambia +all'interno di un \textit{thread} il cambiamento varrà anche per tutti gli +altri. Non esiste quindi con le funzioni classiche un modo semplice per far sì +che i singoli \textit{thread} possano aprire file usando una propria directory +per risolvere i \textit{pathname} relativi. 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 di sistema, chiamate in maniera generica ``\textit{at-functions}'' in -quanto quasi tutte sono contraddistinte dal suffisso \texttt{at}, che -permettono l'apertura di un file (o le rispettive altre operazioni) usando un +funzioni di sistema, chiamate genericamente ``\textit{at-functions}'' in +quanto usualmente contraddistinte dal suffisso \texttt{at}, che permettono +l'apertura di un file (o le rispettive altre operazioni) usando un \textit{pathname} relativo ad una directory specificata.\footnote{l'introduzione è avvenuta su proposta dello sviluppatore principale della \acr{glibc} Urlich Drepper e le corrispondenti @@ -1761,6 +1760,9 @@ specificata.\footnote{l'introduzione è avvenuta su proposta dello sviluppatore 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}.} +Essendo accomunate dalla stessa interfaccia le tratteremo insieme in questa +sezione pur non essendo strettamente attinenti l'I/O su file. + Benché queste funzioni non siano presenti negli standard tradizionali esse sono state adottate da altri sistemi unix-like come Solaris, i vari BSD, fino @@ -1821,15 +1823,14 @@ esame la nuova funzione di sistema \funcd{openat}, il cui prototipo è: Il comportamento di \func{openat} è del tutto analogo a quello di \func{open}, con la sola eccezione del fatto che se per l'argomento \param{pathname} si -utilizza un \textit{pathname} relativo questo, sarà risolto rispetto alla -directory indicata da \param{dirfd}. Qualora invece si usi un +utilizza un \textit{pathname} relativo questo sarà risolto rispetto alla +directory indicata da \param{dirfd}; qualora invece si usi un \textit{pathname} assoluto \param{dirfd} verrà semplicemente ignorato. Infine -se per \param{dirfd} si usa il valore speciale \constd{AT\_FDCWD}, la +se per \param{dirfd} si usa il valore speciale \constd{AT\_FDCWD} la risoluzione sarà effettuata rispetto alla directory di lavoro corrente del -processo. Si tenga presente però che questa costante, 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. +processo. Questa, come le altre costanti \texttt{AT\_*}, è definita in +\headfile{fcntl.h}, per cui per usarla 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 @@ -1837,8 +1838,8 @@ 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 -\textit{pathname} assoluto, nel qual caso, come detto, il valore -di \param{dirfd} sarà completamente ignorato. +\textit{pathname} assoluto, nel qual caso, come detto, il valore di +\param{dirfd} sarà completamente ignorato. \begin{table}[htb] \centering @@ -1850,20 +1851,20 @@ di \param{dirfd} sarà completamente ignorato. \hline \func{execveat} &$\bullet$&\func{execve} \\ \func{faccessat} &$\bullet$&\func{access} \\ - \funcm{fchmodat} &$\bullet$&\func{chmod} \\ + \func{fchmodat} &$\bullet$&\func{chmod} \\ \func{fchownat} &$\bullet$&\func{chown},\func{lchown}\\ - \funcm{fstatat} &$\bullet$&\func{stat},\func{lstat} \\ + \func{fstatat} &$\bullet$&\func{stat},\func{lstat} \\ \funcm{futimesat}& -- & obsoleta \\ - \func{linkat} &$\bullet$\footnotemark&\func{link} \\ + \func{linkat} &$\bullet$&\func{link} \\ \funcm{mkdirat} & -- &\func{mkdir} \\ \funcm{mkfifoat} & -- &\func{mkfifo} \\ \funcm{mknodat} & -- &\func{mknod} \\ \func{openat} & -- &\func{open} \\ \funcm{readlinkat}& -- &\func{readlink}\\ - \funcm{renameat} & -- &\func{rename} \\ - \funcm{renameat2}& -- &\func{rename} \\ + \func{renameat} & -- &\func{rename} \\ + \func{renameat2}\footnotemark& -- &\func{rename} \\ \funcm{scandirat}& -- &\func{scandir} \\ - \funcm{statx} &$\bullet$&\func{stat} \\ + \func{statx} &$\bullet$&\func{stat} \\ \funcm{symlinkat}& -- &\func{symlink} \\ \func{unlinkat} &$\bullet$&\func{unlink},\func{rmdir} \\ \func{utimensat} &$\bullet$&\func{utimes},\func{lutimes}\\ @@ -1874,39 +1875,109 @@ di \param{dirfd} sarà completamente ignorato. \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.} +\footnotetext{anche se la funzione ha un argomento \param{flags} questo + attiene a funzionalità specifiche della stessa e non all'uso generico fatto + nelle altre \textit{at-functions}, pertanto lo si è indicato come assente.} 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 +classica. Tutte seguono la convenzione appena vista per \func{openat}, in cui +agli argomenti della funzione classica viene anteposto l'argomento +\param{dirfd}. Per alcune, 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}. - -Per le funzioni che lo prevedono l'ulteriore argomento \param{flag} è stato -introdotto per fornire un meccanismo con cui modificarne il comportamento. Il -solo caso generale, valido per tutte, è quello in cui si sta operando su un -collegamento simbolico, e si vuole poter scegliere se far agire la funzione -direttamente sullo stesso o sul file da esso referenziato. Ma oltre a questo -caso generico, l'argomento viene usato per controllare ulteriori -caratteristiche di funzionamento, dipendenti dalla funzione stessa, per cui -deve essere comunque passato come maschera binaria ed impostato usando i -valori delle appropriate costanti \texttt{AT\_*}, definite in -\headfile{fcntl.h}. +anche l'aggiunta di un argomento finale, \param{flags}, che è stato introdotto +per fornire un meccanismo con cui modificarne il comportamento. + +Per tutte quelle che non hanno un argomento aggiuntivo il comportamento è +identico alla corrispondente funzione ordinaria, pertanto non le tratteremo +esplicitamente, vale per loro quanto detto con \func{openat} per l'uso del +nuovo argomento \param{dirfd}. Tratteremo invece esplicitamente tutte quelle +per cui l'argomento è presente, in quanto il loro comportamento viene +modificato a seconda del valore assegnato a \param{flags}; questo deve essere +passato come maschera binaria con una opportuna combinazione delle costanti +elencate in tab.~\ref{tab:at-functions_constant_values}, in quanto sono +possibili diversi valori a seconda della funzione usata. -%% Verificare uso generico di AT_EMPTY_XX +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|p{8cm}|} + \hline + \textbf{Costante} & \textbf{Significato} \\ + \hline + \hline + \constd{AT\_EMPTY\_PATH} & Usato per operare direttamente (specificando + una stringa vuota per il \texttt{pathname}) + sul file descriptor \param{dirfd} che in + questo caso può essere un file qualunque.\\ + \constd{AT\_SYMLINK\_NOFOLLOW}& Se impostato la funzione non esegue la + dereferenziazione dei collegamenti + simbolici.\\ + \hline + \constd{AT\_EACCES} & Usato solo da \func{faccessat}, richiede che + il controllo dei permessi sia fatto usando + l'\ids{UID} effettivo invece di quello + reale.\\ + \constd{AT\_NO\_AUTOMOUNT} & Usato solo da \func{fstatat} e \func{statx}, + evita il montaggio automatico qualora + \param{pathname} faccia riferimento ad una + directory marcata per + l'\textit{automount}\footnotemark + (dal kernel 2.6.38).\\ + \constd{AT\_REMOVEDIR} & Usato solo da \func{unlinkat}, richiede che + la funzione si comporti come \func{rmdir} + invece che come \func{unlink}.\\ + \constd{AT\_SYMLINK\_FOLLOW}& Usato solo da \func{linkat}, se impostato la + funzione esegue la dereferenziazione dei + collegamenti simbolici.\\ + \hline + \end{tabular} + \caption{Le costanti utilizzate per i bit dell'argomento aggiuntivo + \param{flags} delle \textit{at-functions}, definite in + \headfile{fcntl.h}.} + \label{tab:at-functions_constant_values} +\end{table} -Come esempio delle funzioni che lo utilizzano solo nel caso generico possiamo -considerare \funcd{fchownat}, che può essere usata per sostituire sia -\func{chown} che \func{lchown}; il suo prototipo è: +\footnotetext{si tratta di una funzionalità fornita dal kernel che consente di + montare automaticamente una directory quando si accede ad un + \textit{pathname} al di sotto di essa, per i dettagli, più di natura + sistemistica, si può consultare sez.~5.1.6 di \cite{AGL}.} + +Si tenga presente che non tutte le funzioni che prevedono l'argomento +aggiuntivo sono \textit{system call}, ad esempio \func{faccessat} e +\func{fchmodat} sono realizzate con dei \textit{wrapper} nella \acr{glibc} per +aderenza allo standard POSIX.1-2008, dato che la \textit{system call} +sottostante non prevede l'argomento \param{flags}. + +In tab.~\ref{tab:at-functions_constant_values} si sono elencati i valori +utilizzabili per i flag (tranne quelli specifici di \func{statx} su cui +torneremo più avanti), mantenendo nella prima parte quelli comuni usati da più +funzioni. Il primo di questi è \const{AT\_SYMLINK\_NOFOLLOW}, che viene usato +da tutte le funzioni tranne \func{linkat} e \func{unlinkat}, e che consente di +scegliere, quando si sta operando su un collegamento simbolico, se far agire +la funzione direttamente sullo stesso o sul file da esso referenziato. Si +tenga presente però che per \funcm{fchmodat} questo, che è l'unico flag +consentito e previsto dallo standard, non è attualmente implementato (anche +perché non avrebbe molto senso cambiare i permessi di un link simbolico) e +pertanto l'uso della funzione è analogo a quello delle altre funzioni che non +hanno l'argomento \param{flags} (e non la tratteremo esplicitamente). + +L'altro flag comune è \const{AT\_EMPTY\_PATH}, utilizzabile a partire dal +kernel 2.6.39, che consente di usare per \param{dirfd} un file descriptor +associato ad un file qualunque e non necessariamente ad una directory; in +particolare si può usare un file descriptor ottenuto aprendo un file con il +flag \param{O\_PATH} (vedi quanto illustrato a +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 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{unistd.h} \fhead{fcntl.h} +\fhead{unistd.h} \fdecl{int fchownat(int dirfd, const char *pathname, uid\_t owner, gid\_t group, int flags)} \fdesc{Modifica il proprietario di un file.} @@ -1923,19 +1994,20 @@ considerare \funcd{fchownat}, che può essere usata per sostituire sia } \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}. +In questo caso, oltre a quanto già detto per \func{openat} riguardo all'uso di +\param{dirfd}, se si è impostato \const{AT\_SYMLINK\_NOFOLLOW} in +\param{flags}, si 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}. La funzione supporta anche l'uso +di \const{AT\_EMPTY\_PATH}, con il significato illustrato in precedenza e non +ha flag specifici. -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 è: +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} \fhead{unistd.h} \fdecl{int faccessat(int dirfd, const char *path, int mode, int flags)} \fdesc{Controlla i permessi di accesso.} @@ -1952,23 +2024,22 @@ prima di queste è \funcd{faccessat}, ed il suo prototipo è: } \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 funzione esegue il controllo di accesso ad un file, e \param{flags} +consente di modificarne il comportamento rispetto a quello ordinario di +\func{access} (cui è analoga, e con cui condivide i problemi di sicurezza +visti in sez.~\ref{sec:file_stat}) usando il valore \const{AT\_EACCES} per +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. -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 è: +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} +\fhead{unistd.h} \fdecl{int unlinkat(int dirfd, const char *pathname, int flags)} \fdesc{Rimuove una voce da una directory.} } @@ -1988,29 +2059,219 @@ alla funzione di comportarsi sia come analogo di \func{unlink} che di 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}. +\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 e +\const{AT\_EMPTY\_PATH} non è supportato) anche se \param{flags} è una +maschera binaria, essendo \const{AT\_REMOVEDIR} l'unico flag disponibile per +questa funzione, lo si può assegnare direttamente. + +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} +\fhead{sys/stat.h} +\fdecl{int utimensat(int dirfd, const char *pathname, const struct + timespec times[2],\\ +\phantom{int utimensat(}int flags)} +\fdesc{Cambia i tempi di un file.} +} + +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} assumerà i valori di \func{utimes}, \func{lutimes} e + \func{futimens} con lo stesso significato ed inoltre: + \begin{errlist} + \item[\errcode{EBADF}] \param{dirfd} non è \const{AT\_FDCWD} o un file + descriptor valido. + \item[\errcode{EFAULT}] \param{dirfd} è \const{AT\_FDCWD} ma + \param{pathname} è \var{NULL} o non è un puntatore valido. + \item[\errcode{EINVAL}] si usato un valore non valido per \param{flags}, + oppure \param{pathname} è \var{NULL}, \param{dirfd} non è + \const{AT\_FDCWD} e \param{flags} contiene \const{AT\_SYMLINK\_NOFOLLOW}. + \item[\errcode{ESRCH}] non c'è il permesso di attraversamento per una delle + componenti di \param{pathname}. + \end{errlist} +} +\end{funcproto} + +La funzione imposta i tempi dei file utilizzando i valori passati nel vettore +di strutture \struct{timespec} ed ha in questo lo stesso comportamento di +\func{futimens}, vista in sez.~\ref{sec:file_file_times}, ma al contrario di +questa può essere applicata anche direttamente ad un file come \func{utimes}; +l'unico valore consentito per \param{flags} è \const{AT\_SYMLINK\_NOFOLLOW} +che indica alla funzione di non dereferenziare i collegamenti simbolici, cosa +che le permette di riprodurre anche le funzionalità di \func{lutimes} (con una +precisione dei tempi maggiore). + +Su Linux solo \func{utimensat} è una \textit{system call} mentre +\func{futimens} è una funzione di libreria, infatti \func{utimensat} ha un +comportamento speciale se \param{pathname} è \var{NULL}, in tal caso +\param{dirfd} viene considerato un file descriptor ordinario e il cambiamento +del tempo viene applicato al file sottostante, qualunque esso sia. Viene cioè +sempre usato il comportamento che per altre funzioni deve essere attivato con +\const{AT\_EMPTY\_PATH} (che non è previsto per questa funzione) per cui +\code{futimens(fd, times}) è del tutto equivalente a \code{utimensat(fd, NULL, + times, 0)}. Si tenga presente che nella \acr{glibc} questo comportamento è +disabilitato, e la funzione, seguendo lo standard POSIX, ritorna un errore di +\errval{EINVAL} se invocata in questo modo. + +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} +\fhead{sys/stat.h} +\fdecl{int fstatat(int dirfd, const char *pathname, struct stat *statbuf, int + flags)} +\fdesc{Rimuove una voce da una directory.} +} + +{La funzione ritorna gli stessi valori e gli stessi codici di errore di + \func{stat}, \func{fstat}, o \func{lstat} 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 \textit{pathname} relativo, + ma \param{dirfd} fa riferimento ad un file. + \end{errlist} +} +\end{funcproto} + +La funzione ha lo stesso comportamento delle sue equivalenti classiche, l'uso +di \param{flags} consente di farla comportare come \func{lstat} se si usa +\const{AT\_SYMLINK\_NOFOLLOW}, o come \func{fstat} se si usa con +\const{AT\_EMPTY\_PATH} e si passa il file descriptor in \param{dirfd}. Viene +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} 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} +\fdecl{int linkat(int olddirfd, const char *oldpath, int newdirfd, \\ +\phantom{int linkat(}const char *newpath, int flags)} +\fdesc{Crea un nuovo collegamento diretto (\textit{hard link}).} +} + +{La funzione ritorna gli stessi valori e gli stessi codici di errore di + \func{link}, ed in più: + \begin{errlist} + \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} 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. 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/ + +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 @@ -2020,148 +2281,94 @@ costanti utilizzabili per i valori di \param{flags}. \textbf{Costante} & \textbf{Significato} \\ \hline \hline - \constd{AT\_EACCES} & Usato solo da \func{faccessat}, richiede che - il controllo dei permessi sia fatto usando - l'\ids{UID} effettivo invece di quello - reale.\\ - \constd{AT\_EMPTY\_PATH} & Usato da varie funzioni per operare - direttamente (specificando una stringa vuota - per il \texttt{pathname}) sul file descriptor - \param{dirfd} che in questo caso deve essere - ottenuto aprendo un file, che - può non essere una directory, con il flag - \param{O\_PATH} (vedi - sez.~\ref{sec:file_open_close}).\\ - \constd{AT\_REMOVEDIR} & Usato solo da \func{unlinkat}, richiede che - la funzione si comporti come \func{rmdir} - invece che come \func{unlink}.\\ - \constd{AT\_SYMLINK\_FOLLOW}& Se impostato la funzione esegue la - dereferenziazione dei collegamenti simbolici - (usato esplicitamente solo da - \func{linkat}).\\ - \constd{AT\_SYMLINK\_NOFOLLOW}& Se impostato la funzione non esegue la - dereferenziazione dei collegamenti - simbolici.\\ + \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{Le costanti utilizzate per i bit dell'argomento - aggiuntivo \param{flags} delle \textit{at-functions}.} - \label{tab:at-functions_constant_values} + \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 manca prototipo di renameat2, introdotta nel 3.15, vedi -% http://lwn.net/Articles/569134/ +% 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 % TODO manca prototipo di execveat, introdotta nel 3.19, vedi % https://lwn.net/Articles/626150/ cerca anche fexecve +% TODO: manca prototipo e motivazione di execveat, vedi +% http://man7.org/linux/man-pages/man2/execveat.2.html +% TODO manca prototipo di renameat2, introdotta nel 3.15, vedi +% http://lwn.net/Articles/569134/ -\texttt{ATTENZIONE PARTE DA RIVEDERE} +% TODO: trattare i nuovi AT_flags quando e se arriveranno, vedi +% https://lwn.net/Articles/767547/ -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 \func{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; 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{sys/time.h} -\fdecl{int utimensat(int dirfd, const char *pathname, const struct - timespec times[2], int flags)} -\fdesc{Cambia i tempi di 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{EACCES}] si è richiesta l'impostazione del tempo corrente ma - non si ha il permesso di scrittura sul file, o non si è proprietari del - file o non si hanno i privilegi di amministratore; oppure il file è - immutabile (vedi sez.~\ref{sec:file_perm_overview}). - \item[\errcode{EBADF}] \param{dirfd} non è \const{AT\_FDCWD} o un file - descriptor valido. - \item[\errcode{EFAULT}] \param{times} non è un puntatore valido oppure - \param{dirfd} è \const{AT\_FDCWD} ma \param{pathname} è \var{NULL} o non è - un puntatore valido. - \item[\errcode{EINVAL}] si sono usati dei valori non corretti per i tempi di - \param{times}, oppure è si usato un valore non valido per \param{flags}, - oppure \param{pathname} è \var{NULL}, \param{dirfd} non è - \const{AT\_FDCWD} e \param{flags} contiene \const{AT\_SYMLINK\_NOFOLLOW}. - \item[\errcode{EPERM}] si è richiesto un cambiamento nei tempi non al tempo - corrente, ma non si è proprietari del file o non si hanno i privilegi di - amministratore; oppure il file è immutabile o \textit{append-only} (vedi - sez.~\ref{sec:file_perm_overview}). - \item[\errcode{ESRCH}] non c'è il permesso di attraversamento per una delle - componenti di \param{pathname}. - \end{errlist} - ed inoltre per entrambe \errval{EROFS} e per \func{utimensat} - \errval{ELOOP}, \errval{ENAMETOOLONG}, \errval{ENOENT}, \errval{ENOTDIR} nel - loro significato generico.} -\end{funcproto} - -La funzione imposta i tempi dei file utilizzando i valori passati nel vettore -di strutture \struct{timespec} esattamente come \func{futimes} (si veda quanto -illustrato in sez.~\ref{sec:file_file_times}). - -La funzione supporta invece, rispetto ad \func{utimes} che abbiamo visto in -sez.~\ref{sec:file_file_times}, una sintassi più complessa che consente una -indicazione sicura del file su cui operare specificando la directory su cui si -trova tramite il file descriptor \param{dirfd} ed il suo nome come -\textit{pathname relativo} in \param{pathname}.\footnote{su Linux solo - \func{utimensat} è una \textit{system call} e \func{futimens} è una funzione - di libreria, infatti se \param{pathname} è \var{NULL} \param{dirfd} viene - considerato un file descriptor ordinario e il cambiamento del tempo - applicato al file sottostante, qualunque esso sia, per cui - \code{futimens(fd, times}) è del tutto equivalente a \code{utimensat(fd, - NULL, times, 0)} ma nella \acr{glibc} questo comportamento è disabilitato - seguendo lo standard POSIX, e la funzione ritorna un errore di - \errval{EINVAL} se invocata in questo modo.} - -Torneremo su questa sintassi e sulla sua motivazione in -sez.~\ref{sec:file_openat}, quando tratteremo tutte le altre funzioni (le -cosiddette \textit{at-functions}) che la utilizzano; essa prevede comunque -anche la presenza dell'argomento \param{flags} con cui attivare flag di -controllo che modificano il comportamento della funzione, nel caso specifico -l'unico valore consentito è \const{AT\_SYMLINK\_NOFOLLOW} che indica alla -funzione di non dereferenziare i collegamenti simbolici, cosa che le permette -di riprodurre le funzionalità di \func{lutimes}. - - -\texttt{ATTENZIONE PARTE DA RIVEDERE} \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 - -% TODO: manca prototipo e motivazione di execveat, vedi -% http://man7.org/linux/man-pages/man2/execveat.2.html \subsection{Le operazioni di controllo} \label{sec:file_fcntl_ioctl} @@ -3256,7 +3463,6 @@ sistemi più moderni. % TODO: mettere prototipi espliciti fseeko e ftello o menzione? - \subsection{Input/output binario} \label{sec:file_binary_io}