From: Simone Piccardi Date: Sat, 2 Feb 2019 18:19:49 +0000 (+0100) Subject: Trattata fstatat, e correzioni varie per utimensat. X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=d8e406a9b421815036ee2f12eccca0869a48dceb;hp=b627cb23a7173b4df3739d98329131a57f257278 Trattata fstatat, e correzioni varie per utimensat. --- diff --git a/fileio.tex b/fileio.tex index 7c2a171..975a9c1 100644 --- a/fileio.tex +++ b/fileio.tex @@ -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} @@ -1760,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 @@ -1888,11 +1891,12 @@ 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}. Quando invece l'argomento è presente il -comportamento viene modificato a seconda del valore assegnato a \param{flags}, -che 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. +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. \begin{table}[htb] \centering @@ -1952,11 +1956,11 @@ 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 \func{fchmodat} questo, che è l'unico flag +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}. +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 @@ -1967,13 +1971,13 @@ 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}. -Come esempio di funzione che utilizza solo questi due flag generici possiamo -considerare \funcd{fchownat}, che può essere usata per sostituire sia -\func{chown} che \func{lchown}; il suo prototipo è: +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 è: \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.} @@ -1990,16 +1994,20 @@ considerare \funcd{fchownat}, che può essere usata per sostituire sia } \end{funcproto} -In questo caso se si è impostato \const{AT\_SYMLINK\_NOFOLLOW} 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}. +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. -Un'altra funzione che utilizza l'argomento \param{flags}, usandolo per -indicare altro rispetto alla possibilità di seguire o meno un collegamento -simbolico, è \funcd{faccessat}, ed il suo prototipo è: +Una seconda funzione 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.} @@ -2016,22 +2024,22 @@ simbolico, è \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. Un'altra funzione che ha un utilizzo specifico dell'argomento \param{flags} è -\funcd{unlinkat}: in questo caso l'argomento viene utilizzato perché tramite +\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.} } @@ -2059,6 +2067,97 @@ 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 è: + +\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 analoga delle funzioni \func{stat}, \func{fstat} e \func{lstat} si può +utilizzare invece \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},\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 @@ -2085,24 +2184,17 @@ prototipo è: } \end{funcproto} -In questo caso - -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 +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. -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}. - +Un'altra funzione che @@ -2118,107 +2210,25 @@ costanti utilizzabili per i valori di \param{flags}. % TODO: Trattare esempio di inzializzazione di file e successivo collegamento % con l'uso di O_TMPFILE e linkat, vedi man open +% 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/ -% TODO manca prototipo di execveat, introdotta nel 3.19, vedi -% https://lwn.net/Articles/626150/ cerca anche fexecve % TODO: trattare i nuovi AT_flags quando e se arriveranno, vedi % https://lwn.net/Articles/767547/ -\texttt{ATTENZIONE PARTE DA RIVEDERE} - - -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}