From: Simone Piccardi Date: Sat, 11 Feb 2012 21:21:27 +0000 (+0000) Subject: Revisionate le at-functions X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=140842fd978f9d700c90078360cfbf205456e674 Revisionate le at-functions --- diff --git a/fileio.tex b/fileio.tex index 37bb9f3..bb5c99b 100644 --- a/fileio.tex +++ b/fileio.tex @@ -1463,14 +1463,14 @@ comportamento può essere controllato attraverso il file scrivere in questo file si consulti la documentazione allegata ai sorgenti del kernel nel file \file{Documentation/sysctl/vm.txt}, trattandosi di argomenti di natura sistemistica non li prenderemo in esame.} Si tenga -presente che la funzione di sistema \funcm{bdflush} che un tempo veniva usata -per queste impostazioni è deprecata e causa semplicemente la stampa di un +presente che la funzione di sistema \funcm{bdflush}, che un tempo veniva usata +per queste impostazioni, è deprecata e causa semplicemente la stampa di un messaggio nei log del kernel, pertanto non la prenderemo in esame. -Quando si vogliono scaricare soltanto i dati di un singolo file (ad esempio -essere sicuri che i dati di un database sono stati registrati su disco) si -possono usare le due funzioni di sistema \funcd{fsync} e \funcd{fdatasync}, i -cui prototipi sono: +Quando si vogliano scaricare i dati di un singolo file, ad esempio essere +sicuri che i dati di un database siano stati registrati su disco, si possono +usare le due funzioni di sistema \funcd{fsync} e \funcd{fdatasync}, i cui +prototipi sono: \begin{funcproto}{ \fhead{unistd.h} @@ -1500,12 +1500,12 @@ avviene spesso per i database, è assicurarsi che i dati raggiungano il disco e siano rileggibili immediatamente in maniera corretta, è sufficiente l'uso di \func{fdatasync} che non comporta anche l'esecuzione di operazioni non necessarie all'integrità dei dati, come l'aggiornamento dei temi di ultima -modifica (ed ultimo accesso). +modifica ed ultimo accesso. Si tenga presente che l'uso di queste funzioni non comporta la -sincronizzazione della directory che contiene il file (e scrittura della -relativa voce su disco) che se necessaria deve essere effettuata -esplicitamente con \param{sync} sul file descriptor della +sincronizzazione della directory che contiene il file e la scrittura della +relativa voce su disco, che se necessaria deve essere effettuata +esplicitamente con \func{fsync} sul file descriptor della directory.\footnote{in realtà per il filesystem \acr{ext2}, quando lo si monta con l'opzione \cmd{sync}, il kernel provvede anche alla sincronizzazione automatica delle voci delle directory.} @@ -1514,26 +1514,37 @@ L'uso di \func{sync} presenta in certi casi, quando ci sono più filesystem montati, problemi di prestazioni dovute al fatto che la funzione provoca la sincronizzazione dei dati su tutti quanti i filesystem, anche quando interesserebbe che questo avvenga soltanto su quello dei file su cui si sta -lavorando. +lavorando, se i dati in attesa sono molti questo può causare seri problemi di +prestazioni. Per questo motivo è stata introdotta una nuova funzione di sistema, -\funcd{syncfs},\footnote{introdotta a partire dal kernel 2.6.39, la funzione è +\funcd{syncfs},\footnote{la funzione è stata introdotta a partire dal kernel + 2.6.39 ed è accessibile solo se è definita la macro \macro{\_GNU\_SOURCE}, è specifica di Linux e non prevista da nessuno standard.} che effettua lo -scarico dei dati soltanto per il filesystem su cui si sta operando, il cui +scarico dei dati soltanto per il filesystem su cui si sta operando, il suo prototipo è: \begin{funcproto}{ \fhead{unistd.h} -\fdecl{void syncfs(int fd)} +\fdecl{int syncfs(int fd)} \fdesc{Sincronizza il buffer della cache dei file del singolo filesystem col disco.} } -{La funzione non ritorna nulla e non prevede condizioni di errore.} +{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{EBADF}] \param{fd} non è un descrittore valido. + \end{errlist} +} \end{funcproto} +La funzione richiede che si specifichi nell'argomento \param{fd} un file +descriptor su cui si sta operando, e lo scarico dei dati sarà limitato al +filesystem su cui il file ad esso corrispondente si trova. + -\subsection{Le funzioni \func{openat}, \func{mkdirat} e affini} +\subsection{Le \textit{at-functions}: \func{openat} e affini} \label{sec:file_openat} \itindbeg{at-functions} @@ -1541,13 +1552,13 @@ prototipo è: Un problema generale che si pone con l'uso della funzione \func{open}, così come per le altre funzioni che prendono come argomenti dei \itindsub{pathname}{relativo} \textit{pathname} relativi, è la possibilità, -quando un \textit{pathname} relativo non fa riferimento alla -\index{directory~di~lavoro} directory di lavoro corrente, che alcuni dei suoi -componenti vengano modificati in parallelo alla chiamata a \func{open}, cosa -che lascia aperta la possibilità di una \itindex{race~condition} \textit{race - condition} in cui c'è spazio per un \itindex{symlink~attack} \textit{symlink - attack} (si ricordi quanto visto per \func{access} in -sez.~\ref{sec:file_perm_management}). +quando un \textit{pathname} relativo non fa riferimento ad un file posto +direttamente nella \index{directory~di~lavoro} directory di lavoro corrente, +che alcuni dei componenti del \textit{pathname} vengano modificati in +parallelo alla chiamata a \func{open}, cosa che lascia aperta la possibilità +di una \itindex{race~condition} \textit{race condition} in cui c'è spazio per +un \itindex{symlink~attack} \textit{symlink attack} (si ricordi quanto visto +per \func{access} in sez.~\ref{sec:file_perm_management}). Inoltre come già accennato, la \index{directory~di~lavoro} directory di lavoro corrente è una proprietà del singolo processo; questo significa che quando si @@ -1559,52 +1570,49 @@ directory di lavoro. 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, dette anche funzioni ``\textit{at}'' in quanto contraddistinte dal +funzioni, dette anche ``\textit{at-functions}'' in quanto contraddistinte dal suffisso \texttt{at}, che permettono l'apertura di un file (o le rispettive altre operazioni) usando un \itindsub{pathname}{relativo} \textit{pathname} relativo ad una directory specificata.\footnote{l'introduzione è avvenuta su - proposta dello sviluppatore principale delle \acr{glibc} Urlich Drepper; le - corrispondenti \textit{system call} sono state inserite nel kernel ufficiale - a partire dalla versione 2.6.16, in precedenza era disponibile una - emulazione che, sia pure con 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}.} Benché queste funzioni non -siano presenti negli standard tradizionali esse sono state adottate da vari -Unix\footnote{oltre a Linux e Solaris sono presenti in vari BSD.} fino ad -essere incluse nella recente revisione (la POSIX.1-2008) dello standard -POSIX.1; con le \acr{glibc} per l'accesso a queste funzioni è necessario + proposta dello sviluppatore principale della \acr{glibc} Urlich Drepper e le + corrispondenti \textit{system call} sono state inserite nel kernel a partire + dalla versione 2.6.16, in precedenza era disponibile una emulazione che, sia + pure con 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}.} +Benché queste funzioni non siano presenti negli standard tradizionali esse +sono state adottate da altri sistemi unix-like com Solaris i vari BSD, fino ad +essere incluse in una recente revisione (la POSIX.1-2008) dello standard +POSIX.1. Con la \acr{glibc} per l'accesso a queste funzioni è necessario definire la macro \macro{\_ATFILE\_SOURCE}. L'uso di queste funzioni prevede una apertura iniziale della directory che sarà la base della risoluzione dei \itindsub{pathname}{relativo} \textit{pathname} relativi che verranno usati in seguito, dopo di che si dovrà passare il relativo file descriptor alle varie funzioni che useranno quella -directory come punto di partenza per la risoluzione.\footnote{in questo modo, - anche quando si lavora con i \itindex{thread} \textit{thread}, si può - mantenere una \index{directory~di~lavoro} directory di lavoro diversa per - ciascuno di essi.} +directory come punto di partenza per la risoluzione. In questo modo, anche +quando si lavora con i \itindex{thread} \textit{thread}, si può mantenere una +\index{directory~di~lavoro} directory di lavoro diversa per ciascuno di essi. Questo metodo, oltre a risolvere i problemi di \itindex{race~condition} \textit{race condition}, consente anche di ottenere aumenti di prestazioni significativi quando si devono eseguire molte operazioni su sezioni dell'albero dei file che prevedono delle gerarchie di sottodirectory molto -profonde; infatti in questo caso basta eseguire la risoluzione del +profonde. Infatti in questo caso basta eseguire la risoluzione del \textit{pathname} della directory di partenza una sola volta (nell'apertura iniziale) e non tutte le volte che si deve accedere a ciascun file che essa contiene. La sintassi generale di queste nuove funzioni è che esse prevedono come primo -argomento il file descriptor della directory da usare come base, mentre gli -argomenti successivi restano identici a quelli della corrispondente funzione -ordinaria; ad esempio nel caso di \funcd{openat} avremo che essa è definita -come: +argomento il file descriptor della directory da usare come base per la +risoluzione dei nomi, mentre gli argomenti successivi restano identici a +quelli della corrispondente funzione ordinaria. Se ad esempio prendiamo in +esame la nuova funzione di sistema \funcd{openat}, avremo il prototipo: \begin{funcproto}{ \fhead{fcntl.h} \fdecl{int openat(int dirfd, const char *pathname, int flags)} -\fdecl{int openat(int dirfd, const char *pathname, int flags, mode\_t - mode))} +\fdecl{int openat(int dirfd, const char *pathname, int flags, mode\_t mode)} \fdesc{Apre un file a partire da una directory di \index{directory~di~lavoro} lavoro.} } @@ -1623,37 +1631,23 @@ Il comportamento delle nuove funzioni è del tutto analogo a quello delle corrispettive classiche, con la sola eccezione del fatto che se fra i loro argomenti si utilizza un \itindsub{pathname}{relativo} \textit{pathname} relativo questo sarà risolto rispetto alla directory indicata -da \param{dirfd}; qualora invece si usi un \itindsub{pathname}{assoluto} +da \param{dirfd}. Qualora invece si usi un \itindsub{pathname}{assoluto} \textit{pathname} assoluto \param{dirfd} verrà semplicemente ignorato. Infine -se per \param{dirfd} si usa il valore speciale -\const{AT\_FDCWD},\footnote{questa, 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.} la risoluzione sarà effettuata rispetto alla directory di -\index{directory~di~lavoro} lavoro corrente del processo. +se per \param{dirfd} si usa il valore speciale \const{AT\_FDCWD}, la +risoluzione sarà effettuata rispetto alla directory di +\index{directory~di~lavoro} lavoro corrente del processo. Si tenga presente +però che questa, 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. Così come il comportamento, anche i valori di ritorno e le condizioni di errore delle nuove funzioni sono gli stessi delle funzioni classiche, agli 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.\footnote{tranne il caso in cui si sia - specificato un \itindsub{pathname}{assoluto} \textit{pathname} assoluto, nel - qual caso, come detto, il valore di \param{dirfd} sarà completamente - ignorato.} - -In tab.~\ref{tab:file_atfunc_corr} si sono riportate le funzioni introdotte -con questa nuova interfaccia, con a fianco la corrispondente funzione -classica.\footnote{in realtà, come visto in sez.~\ref{sec:file_temp_file}, le - funzioni \func{utimes} e \func{lutimes} non sono propriamente le - corrispondenti di \func{utimensat}, dato che questa ha una maggiore - precisione nella indicazione dei tempi dei file.} 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}.\footnote{non staremo pertanto a riportarle una per - una.} Per una parte di queste, 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}. +riferimento ad una directory, tranne il caso in cui si sia specificato un +\itindsub{pathname}{assoluto} \textit{pathname} assoluto, nel qual caso, come +detto, il valore di \param{dirfd} sarà completamente ignorato. \begin{table}[htb] \centering @@ -1664,9 +1658,9 @@ prevista anche l'aggiunta di un ulteriore argomento finale, \param{flags}. \hline \hline \func{faccessat} &$\bullet$&\func{access} \\ - \func{fchmodat} &$\bullet$&\func{chmod} \\ + \funcm{fchmodat} &$\bullet$&\func{chmod} \\ \func{fchownat} &$\bullet$&\func{chown},\func{lchown}\\ - \func{fstatat} &$\bullet$&\func{stat},\func{lstat} \\ + \funcm{fstatat} &$\bullet$&\func{stat},\func{lstat} \\ \func{utimensat} &$\bullet$&\func{utimes},\func{lutimes}\\ \func{linkat} &$\bullet$\footnotemark&\func{link} \\ \funcm{mkdirat} & -- &\func{mkdir} \\ @@ -1687,8 +1681,17 @@ prevista anche l'aggiunta di un ulteriore argomento finale, \param{flags}. \footnotetext{in questo caso l'argomento \param{flags} è disponibile ed utilizzabile solo a partire dal kernel 2.6.18.} -% TODO manca prototipo di fchmodat, verificare se metterlo o metter menzione -% TODO manca prototipo di fstatat, verificare se metterlo o metter menzione +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 +tab.~\ref{tab:file_atfunc_corr}, oltre al nuovo argomento iniziale, è prevista +anche l'aggiunta di un ulteriore argomento finale, \param{flags}. + + % TODO manca prototipo di linkat, verificare se metterlo o metter menzione % TODO manca prototipo di utimensat, verificare se metterlo o metter menzione @@ -1727,18 +1730,15 @@ che \func{lchown}; il suo prototipo è: 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}\footnote{in \headfile{fcntl.h} è - definito anche \const{AT\_SYMLINK\_FOLLOW}, che richiede di dereferenziare i - collegamenti simbolici, essendo questo però il comportamento adottato per un - valore nullo di \param{flags} questo valore non viene mai usato.} 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}. +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}. Come accennato fra tutte quelle marcate in tab.~\ref{tab:file_atfunc_corr} -solo due funzioni possono usare l'argomento \param{flags} con valori diversi -da \const{AT\_SYMLINK\_NOFOLLOW}, la prima di queste è \funcd{faccessat}, ed -il suo prototipo è: +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 è: \begin{funcproto}{ \fhead{unistd.h} @@ -1757,23 +1757,20 @@ il suo prototipo è: } \end{funcproto} -La funzione esegue lo stesso controllo di accesso effettuabile con -\func{access}, ma si può utilizzare l'argomento \param{flags} per modificarne -il comportamento rispetto a quello ordinario di \func{access}. In questo caso -esso può essere specificato come maschera binaria di due valori: -\begin{basedescript}{\desclabelwidth{3.0cm}} -\item[\const{AT\_EACCES}] se impostato \funcd{faccessat} esegue il controllo - dei permessi usando l'\ids{UID} effettivo invece di quello reale (il - comportamento di default, che riprende quello di \func{access}). -\item[\const{AT\_SYMLINK\_NOFOLLOW}] se impostato \funcd{faccessat} non esegue - la dereferenziazione dei collegamenti simbolici, effettuando il controllo - dei permessi direttamente sugli stessi. -\end{basedescript} +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 seconda eccezione è \func{unlinkat}, in questo caso l'ulteriore -argomento \param{flags} viene utilizzato perché tramite esso la funzione possa -comportarsi sia come analogo di \func{unlink} che di \func{rmdir}; il suo -prototipo è: + +La seconda eccezione è \funcd{unlinkat}, in questo caso +l'argomento \param{flags} viene utilizzato perché tramite esso si può indicare +alla fuzione di comportarsi sia come analogo di \func{unlink} che di +\func{rmdir}; il suo prototipo è: \begin{funcproto}{ \fhead{fcntl.h} @@ -1796,20 +1793,73 @@ prototipo è: 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},\footnote{anche se \param{flags} è una maschera binaria, - essendo questo l'unico flag disponibile per questa funzione, lo si può - assegnare direttamente.} essa si comporterà come \func{rmdir}, in tal +\const{AT\_REMOVEDIR}, essa si comporterà come \func{rmdir}, in tal caso \param{pathname} deve essere una directory, che sarà rimossa qualora -risulti vuota. +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}. -\itindend{at-functions} +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|p{8cm}|} + \hline + \textbf{Costante} & \textbf{Significato} \\ + \hline + \hline + \const{AT\_SYMLINK\_NOFOLLOW}& se impostato la funzione non esegue la + dereferenziazione dei collegamenti simbolici.\\ + \const{AT\_SYMLINK\_FOLLOW}& se impostato la funzione esegue la + dereferenziazione dei collegamenti simbolici + (usato esplicitamente solo da \func{linkat}).\\ + \const{AT\_EACCES} & usato solo da \func{faccessat}, richiede che + il controllo dei permessi sia fatto usando + l'\ids{UID} effettivo invece di quello + reale.\\ + \const{AT\_REMOVEDIR} & usato solo da \func{unlinkat}, richiede che + la funzione si comporti come \func{rmdir} + invece che come \func{unlink}.\\ + \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} +\end{table} -% 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 +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 \funcm{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. +% NOTA: manca prototipo di utimensat, per ora si lascia una menzione +\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 \subsection{La funzione \func{fcntl}}