X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileio.tex;h=40dcd9f94ee29c3c3206ccca0eefd415b474cdfd;hp=d2522e1442955588d0147419db29764fdb6eeed0;hb=5da5870ef70a2b793118d14ec547a293927c0d3c;hpb=4be39dd3718d708ccff65b01a8f634e05b56f3c9 diff --git a/fileio.tex b/fileio.tex index d2522e1..40dcd9f 100644 --- a/fileio.tex +++ b/fileio.tex @@ -1361,16 +1361,22 @@ entrambi. Questo consente una sorta di ``\textsl{sincronizzazione}'' automatica della posizione sul file fra padre e figlio che occorre tenere presente. +\itindbeg{close-on-exec} + Si noti inoltre che in questo caso anche i flag di stato del file, essendo mantenuti nella struttura \kstruct{file} della \textit{file table}, vengono condivisi, per cui una modifica degli stessi con \func{fcntl} (vedi sez.~\ref{sec:file_fcntl_ioctl}) si applicherebbe a tutti processi che condividono la voce nella \textit{file table}. Ai file però sono associati -anche altri flag, dei quali l'unico usato al momento è \constd{FD\_CLOEXEC}, -detti \itindex{file~descriptor~flags} \textit{file descriptor flags}; questi -invece sono mantenuti in \kstruct{file\_struct}, e perciò sono locali per -ciascun processo e non vengono modificati dalle azioni degli altri anche in -caso di condivisione della stessa voce della \textit{file table}. +anche altri flag detti \itindex{file~descriptor~flags} \textit{file descriptor + flags}. Questi invece sono mantenuti in \kstruct{file\_struct}, e perciò +sono locali per ciascun processo e non vengono modificati dalle azioni degli +altri anche in caso di condivisione della stessa voce della \textit{file + table}; l'unico usato al momento è quello di \textit{close-on-exec} che +indica che il file descriptor deve essere chiuso in una \func{exec} (vedi +sez.~\ref{sec:proc_exec}). + +\itindend{close-on-exec} Si tenga presente dunque che in un sistema unix-like è sempre possibile per più processi accedere in contemporanea allo stesso file e che non esistono, a @@ -1467,7 +1473,7 @@ L'unica differenza fra due file descriptor duplicati è che ciascuno avrà un suo \textit{file descriptor flag} indipendente. A questo proposito deve essere tenuto presente che nel caso in cui si usi \func{dup} per duplicare un file descriptor, se questo ha il flag di \textit{close-on-exec} attivo (vedi -sez.~\ref{sec:proc_exec} e sez.~\ref{sec:file_fcntl_ioctl}), questo verrà +sez.~\ref{sec:proc_exec} e sez.~\ref{sec:file_shared_access}), questo verrà cancellato nel file descriptor restituito come copia. L'uso principale di questa funzione è nella shell per la redirezione dei file @@ -1764,7 +1770,6 @@ specificata.\footnote{l'introduzione è avvenuta su proposta dello sviluppatore 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 ad essere incluse in una recente revisione dello standard POSIX.1 (la @@ -1939,10 +1944,11 @@ possibili diversi valori a seconda della funzione usata. \label{tab:at-functions_constant_values} \end{table} -\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}.} +\footnotetext{l'\textit{automount} \itindex{automount} è 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, di natura prevalentemente 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 @@ -2136,7 +2142,7 @@ utilizzare invece la funzione di sistema \funcd{fstatat}, il cui prototipo è: \fhead{sys/stat.h} \fdecl{int fstatat(int dirfd, const char *pathname, struct stat *statbuf, int flags)} -\fdesc{Rimuove una voce da una directory.} +\fdesc{Legge le informazioni di un file.} } {La funzione ritorna gli stessi valori e gli stessi codici di errore di @@ -2231,7 +2237,6 @@ consentirebbe rendere accessibile all'interno di un \textit{choot} (vedi sez.~\ref{sec:file_chroot}) un qualunque file sia stato aperto fuori dallo stesso prima di entrarvi. - % NOTE per la discussione sui problemi di sicurezza relativi a questa % funzionalità vedi http://lwn.net/Articles/562488/ @@ -2239,52 +2244,73 @@ Per questo motivo l'uso di \const{AT\_EMPTY\_PATH} richiede comunque privilegi amministrativi, anche se, quando è disponibile il filesystem \texttt{/proc}, è possibile usare \func{linkat} per creare un file da un qualunque file descriptor un processo abbia aperto, usandola con un codice analogo al -seguente:\footnote{non esiste, al momento, una modalità per evitare i rischi - illustrati in precedenza se si sta usando il filesystem \textit{proc}.} +seguente:\footnote{non esiste al momento, se si sta usando il filesystem + \textit{proc}, una modalità per evitare i rischi illustrati in precedenza.} \includecodesnip{listati/procfd_linkat.c} - -Questa modalità è anche quella con cui è possibile assegnare in un secondo +e questa modalità è anche quella con cui è possibile assegnare in un secondo tempo il nome ad un file anonimo creato usando \func{open} con \const{O\_TMPFILE}; ma si deve tenere presente che per questi file la funzione -ha un comportamento particolare. In generale infatti quando il file sorgente -di \func{linkat} ha un numero di collegamenti nulli (cosa che avviene ad -esempio quando si apre un file temporaneo e lo si cancella subito dopo oppure -quando viene cancellato un file aperto in precedenza) la funzione non consente -di ricollegarlo ad un altro file riassegnandogli un nuovo nome e fallisce -sempre, qualunque siano i permessi del processo e che si usi questo approccio -o \const{AT\_EMPTY\_PATH}, con un errore di \errval{ENOENT}. - -Questo non avviene se il file descriptor sorgente è stato ottenuto con -\const{O\_TMPFILE} e la funzione ha successo, a meno che non si sia usato -nell'apertura anche \const{O\_EXCL} per impedire questo specifico -comportamento, e continuare ad ottenere l'errore di \errval{ENOENT}. In fig. - -Pertanto la modalità per creare in maniera sicura la versione iniziale di un -file cui abbiamo accennato a pag.~\pageref{open_o_tmpfile_flag}, - +ha un comportamento particolare. + +In generale infatti quando il file sorgente di \func{linkat} ha un numero di +collegamenti nulli (cosa che avviene ad esempio quando si apre un file +temporaneo e lo si cancella subito dopo oppure quando viene cancellato un file +aperto in precedenza) la funzione non consente di ricollegarlo ad un altro +file riassegnandogli un nuovo nome e fallisce sempre con un errore di +\errval{ENOENT} qualunque siano i permessi del processo, e che si usi questo +approccio o \const{AT\_EMPTY\_PATH}. Ma questo non avviene se il file +descriptor è stato ottenuto con \const{O\_TMPFILE}, in tal caso la funzione ha +successo, a meno che non si sia usato nell'apertura anche \const{O\_EXCL} per +impedire questo comportamento, e continuare ad ottenere \errval{ENOENT}. + +In fig.~\ref{fig:initfile} si è riportato il codice della funzione +\func{InitFile}, che consente di creare in maniera sicura il contenuto +iniziale di un file utilizzando \const{O\_TMPFILE} e \func{linkat}, come +accennato a pag.~\pageref{open_o_tmpfile_flag}. La funzione richiede di +indicare il file da creare usando la sintassi delle \textit{at-functions}, +specificando la directory in cui crearlo con il corrispondente file descriptor +passato nell'argomento \texttt{dirfd} ed il pathname relativo ed essa passato +l'argomento \texttt{file}; il contenuto iniziale del file deve essere fornito +nel buffer \texttt{buf} di lunghezza \texttt{size}. + \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{\codesamplewidth} - \includecodesample{listati/initfile.c} + \includecodesample{listati/InitFile.c} \end{minipage} - \caption{Esempio di codice creare in maniera sicura il contenuto iniziale di - un file.} + \caption{Esempio di codice per creare in maniera sicura il contenuto + iniziale di un file.} \label{fig:initfile} \end{figure} - - - - - -% 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/ - +La funzione come primo passo (\texttt{\small 6--10}) ottiene un file +descriptor accessibile in lettura/scrittura invocando \func{openat} con il +flag \const{O\_TMPFILE} per ottenere un file anonimo, facendo riferimento a +quella che sarà la directory di destinazione in cui poi verrà collegato lo +stesso passata dal chiamante in \texttt{dirfd}, usando ``\texttt{.}'' come +\textit{pathname} relativo. Si noti come nella chiamata si impostino anche +(per semplicità si è usato un valore fisso) i valori iniziali dei permessi del +file (lettura e scrittura solo per il proprietario), e come dopo la chiamata +si controlli la presenza di un eventuale errore, ritornandolo con un messaggio +qualora avvenga. + +Il secondo passo (\texttt{\small 11--15}) è quello di chiamare la funzione +\func{FullWrite} (che tratteremo in dettaglio in sez.~\ref{sec:sock_io_behav}) +per eseguire la scrittura del contenuto del buffer \texttt{buf} sul file +anonimo ottenuto con \func{openat}; in sostanza la funzione scrive tutto il +contenuto del buffer, iterando le scritture qualora non sia possibile eseguire +tutto con una singola \func{write}, cosa che comunque per i file su disco in +genere non avviene mai. + +Una volta completata con successo la scrittura l'ultimo passo (\texttt{\small + 17--23}) è collegare il file anonimo con \func{linkat}, per questo però +occorre utilizzare il \textit{pathname} ad esso associato sotto +\texttt{/proc}, che viene ottenuto (\texttt{\small 16}) con una +\func{snprintf} (vedi sez.~\ref{sec:file_formatted_io}) usando file descriptor +restituito da \func{openat}. Con questo \textit{pathname} si può procedere +(\texttt{\small 17}) a chiamare \func{linkat} per eseguire il collegamento, in +cui occorre usare il flag \const{AT\_SYMLINK\_NOFOLLOW} come nell'esempio +precedente. Altre due funzioni che utilizzano due \textit{pathname} (e due file descriptor) sono \funcd{renameat} e \funcd{renameat2}, corrispondenti alla @@ -2333,15 +2359,13 @@ 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 relative 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}. +L'uso di \func{renameat} è identico a quello di \func{rename}, con la sintassi +delle \textit{at-functions} applicabile 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à specifiche di Linux non previste al momento da nessuno standard +(la funzione è disponibile nelle \acr{glibc} a partire dalla versione 2.28). \begin{table}[htb] \centering @@ -2370,13 +2394,12 @@ 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. +\constd{RENAME\_EXCHANGE}; se specificato la funzione rinomina in un colpo +solo \param{oldpath} in \param{newpath} e \param{newpath} in +\param{oldpath}. Usando questo flag, entrambi i \textit{pathname} passati come +argomenti devono esistere, e non è possibile usare \const{RENAME\_NOREPLACE}, +non ci sono infine restrizioni sul tipo di file (regolare, directory, link +simbolici, dispositivo) 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 @@ -2392,38 +2415,427 @@ Infine il flag \constd{RENAME\_WHITEOUT}, introdotto con il kernel 3.18, richiede un approfondimento 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. +filesystem. Un \textit{overlay} o \textit{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 +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 un oggetto speciale del filesystem, chiamato +\textit{whiteout}, che serve a renderlo non più visibile. La funzione consente +di creare questo oggetto, che in un filesystem ordinario verrebbe visto come +un file di dispositivo con \textit{major minor} e \textit{minor number} nulli, +in maniera atomica quando si rinomina un file. Dato che l'uso di +\const{RENAME\_WHITEOUT} comporta in sostanza la creazione di un file di +dispositivo, l'operazione è privilegiata (occorre la \textit{capability} +\texttt{CAP\_MKNOD}), inoltre occorre anche il supporto nel filesystem usato +come supporto per la scrittura. Infine l'operazione non è compatibile con +\const{RENAME\_EXCHANGE}. \itindend{overlay~filesytem} \itindend{union~filesytem} +Benché non rientri nelle \textit{at-functions} previste nello standard +POSIX.1-2008, tratteremo qui anche la funzione di sistema \funcd{statx}, +introdotta con il kernel 4.11 e disponibile dalle versione 2.28 della +\acr{glibc}, il cui prototipo è: + +\begin{funcproto}{ +\fhead{sys/types.h} +\fhead{sys/stat.h} +\fhead{unistd.h} +\fhead{fcntl.h} +\fdecl{int statx(int dirfd, const char *pathname, int flags, \\ +\phantom{int statx(}unsigned int mask, struct statx *statxbuf)} +\fdesc{Legge le informazioni di un file.} +} + +{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 o \param{mask} + ha un valore riservato. + \item[\errcode{ENOTDIR}] \param{pathname} è un \textit{pathname} relativo, + ma \param{dirfd} fa riferimento ad un file. + \end{errlist} +} +\end{funcproto} + +La funzione è una estensione specifica di Linux consente di leggere le +informazioni di un file; ha la stessa sintassi di \func{fstatat} utilizzando +con lo stesso significato gli argomenti \param{dirfd} e \param{pathname} ed i +valori \const{AT\_EMPTY\_PATH}, \const{AT\_NO\_AUTOMOUNT} e +\const{AT\_SYMLINK\_NOFOLLOW} per \param{flags}. Si può pertanto indicare il +file di cui si vogliono ottenere i dati con un \textit{pathname} assoluto, con +un \textit{pathname} relativo (sia alla directory corrente che a quella +indicata da \param{dirfd}) o con un file descriptor ad esso associato. + +La funzione però consente di ottenere informazioni più dettagliate rispetto a +quelle fornite dalle funzioni tradizionali come \func{stat} e \func{fstatat}, +ed è in grado di controllare le modalità con cui le ottiene nel caso un file +sia posto su un filesystem remoto. Per questo, oltre ai tre valori +precedenti, l'argomento \param{flags} consente anche gli ulteriori valori +elencati in tab.~\ref{tab:statx_flags_const}, con il significato ivi +illustrato. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|p{8cm}|} + \hline + \textbf{Costante} & \textbf{Significato} \\ + \hline + \hline + \constd{AT\_STATX\_SYNC\_AS\_STAT}& si comporta esattamente come + \func{stat}, in questo caso (il default + se non viene indicato niente) il + risultato dipende dal tipo di + filesystem.\\ + \constd{AT\_STATX\_FORCE\_SYNC}& richiede che i valori degli attributi + richiesti siano, in caso di un filesystem + di rete, siano sincronizzati con il server + remoto, questo può forzare una scrittura + dei dati (in particolare i tempi del file) + verso lo stesso.\\ + \constd{AT\_STATX\_DONT\_SYNC} & chiede di non sincronizzare nessun dato, + ritornando quanto presente nella cache, + questo significa che i dati potrebbero + essere non coerenti ed aggiornati, ma si + evita, in caso di filesystem di rete, la + necessità di contattare il server remoto.\\ + \hline + \end{tabular} + \caption{Valori specifici di \func{statx} per l'argomento \param{flags}.} + \label{tab:statx_flags_const} +\end{table} + +La funzione restituisce le informazioni relative al file richiesto nella +struttura \struct{statx} puntata dall'argomento \param{statxbuf}. Inoltre +data la quantità di informazioni che possono essere richieste, la funzione +consente, con l'argomento \param{mask} di selezionare quelle volute, questa +deve essere assegnata ad una maschera binaria dei valori illustrati in +tab.~\ref{tab:statx_mask_const}. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|l|} + \hline + \textbf{Costante} & \textbf{Significato} \\ + \hline + \hline + \constd{STATX\_TYPE} & Tipo del file (\texttt{stx\_mode \& S\_IFMT}).\\ + \constd{STATX\_MODE} & Permessi del file (\texttt{stx\_mode \& + \tild{}S\_IFMT}).\\ + \constd{STATX\_NLINK} & Numero di collegamenti (\textit{hard link}, + \texttt{stx\_nlink}).\\ + \constd{STATX\_UID} & Proprietario del file (per \ids{UID}, + \texttt{stx\_uid}).\\ + \constd{STATX\_GID} & Gruppo proprietario del file (per \ids{GID}, + \texttt{stx\_gid}).\\ + \constd{STATX\_ATIME} & Tempo di ultimo accesso (\texttt{stx\_atime}).\\ + \constd{STATX\_MTIME} & Tempo di ultima modifica (\texttt{stx\_mtime}).\\ + \constd{STATX\_CTIME} & Tempo di ultimo cambiamento (\texttt{stx\_ctime}).\\ + \constd{STATX\_INO} & Numero di \textit{inode} (\texttt{stx\_ino}).\\ + \constd{STATX\_SIZE} & Dimensione del file (\texttt{stx\_size}).\\ + \constd{STATX\_BLOCKS}& Numero di blocchi del file (\texttt{stx\_blocks}).\\ + \constd{STATX\_BASIC\_STATS}& Tutte le informazioni precedenti.\\ + \constd{STATX\_BTIME} & Tempo di creazione (\texttt{stx\_btime}).\\ +% \constd{}& .\\ + \constd{STATX\_ALL} & Tutte le informazioni.\\ + \hline + \end{tabular} + \caption{Le costanti per i valori dell'argomento \param{mask} di + \func{statx}.} + \label{tab:statx_mask_const} +\end{table} + +Si tenga presente che il kernel non richiede che \param{mask} contenga solo i +flag di tab.~\ref{tab:statx_mask_const}, valori ulteriori in genere vengono +ignorati ma non si può comunque indicare un valore qualunque in quanto alcuni +bit sono riservati per future estensioni.\footnote{in particolare il bit + \constd{STATX\_\_RESERVED} che se usato causa il fallimento della funzione + con un errore di \errval{EINVAL}.} Inoltre non è detto che tutte le +informazioni richieste con \param{mask} siano disponibili, per questo il +kernel restituisce in un opportuno campo della struttura \struct{statx}, +\var{stx\_mask}, quali sono i dati effettivamente restituiti, che possono in +alcuni casi essere anche di più di quelli richiesti (se l'informazione +aggiuntiva è ottenuta senza costi ulteriori) per cui è normale che questo +valore possa essere diverso da quanto richiesto. +\begin{figure}[!htb] + \footnotesize + \centering + \begin{minipage}[c]{0.8\textwidth} + \includestruct{listati/statx.h} + \end{minipage} + \normalsize + \caption{La struttura \structd{statx} per la lettura delle informazioni dei + file.} + \label{fig:file_statx_struct} +\end{figure} -% 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) +Si è riportata in fig.~\ref{fig:file_statx_struct} la definizione della +struttura \struct{statx} come presente in \headfile{sys/stat.h}; i campi +\var{stx\_mode}, \var{stx\_nlink}, \var{stx\_uid}, \var{stx\_gid}, +\var{stx\_ino}, \var{stx\_size}, \var{stx\_blksize}, \var{stx\_blocks} sono +identici agli analoghi (con prefisso \texttt{st\_}) dell'ordinaria struttura +\struct{stat} illustrata in fig.~\ref{fig:file_stat_struct} e vale per essi +quanto già detto in sez.~\ref{sec:file_stat} e seguenti. + +\begin{figure}[!htb] + \footnotesize + \centering + \begin{minipage}[c]{0.8\textwidth} + \includestruct{listati/statx_timestamp.h} + \end{minipage} + \normalsize + \caption{La struttura \structd{statx\_timestamp} per i tempi dei file con + \func{statx}. } + \label{fig:file_statx_timestamp_struct} +\end{figure} + +Anche i campi \var{stx\_atime}, \var{stx\_mtime}, \var{stx\_ctime} mantengono +questa analogia, ma esprimono i tempi di ultimo accesso, modifica e +cambiamento con una precisione ed estensione maggiore grazie all'uso di una +struttura dedicata \struct{statx\_timestamp} (riportata in +fig.~\ref{fig:file_statx_timestamp_struct}) che consente di estendere i tempi +dei file ad una granularità del nanosecondo e con un valore dello \textit{unix + time} (vedi sez.~\ref{sec:sys_unix_time}) a 64 bit, che non darà problemi di +overflow per parecchio tempo (sicuramente ben oltre la durata di questa +guida). + +Oltre ai precedenti, e a \val{stx\_mask} che abbiamo già visto e che indica +quali delle informazioni richieste alla funzione sono state fornite, +\func{statx} prevede una serie di informazioni aggiuntive fornite in +altrettanti nuovi campi, illustrati nell'elenco seguente. È comunque previsto +che in futuro \struct{statx} venga estesa per supportare ulteriori +informazioni. + +\begin{basedescript}{\desclabelwidth{1.6cm}\desclabelstyle{\nextlinelabel}} +\item[\var{stx\_btime}] In questo campo viene restituito il \textsl{tempo di + creazione} del file. Come detto in sez.~\ref{sec:file_file_times} questo + tempo normalmente non esiste in un sistema \textit{unix-like}, ma per + migliorare l'interoperabilità è stato aggiunto nelle versioni più recenti di + vari filesystem (come XFS, \acr{ext4}, ecc.) in modo che possa essere + utilizzato da servizi di condivisione dei file (è usato da \textsl{Samba}, + ed è previsto nello standard di NFSv4). +\item[\var{stx\_attributes\_mask}] in questo campo viene restituita una + maschera che indica quali sono i bit restituiti in \var{stx\_attributes} + effettivamente supportati per il file, e per poter utilizzare quest'ultimo + occorre sempre eseguire un AND aritmetico con \var{stx\_attributes\_mask} per + ottenere i valori validi. +\item[\var{stx\_attributes}] in questo campo vengono restituiti gli eventuali + attributi addizionali posseduti dal file. Gran parte di questi sono quelli + impostati con i comandi \cmd{lsattr} e \cmd{chattr} ed abbiamo già incontrato + alcuni di essi in sez.~\ref{sec:file_perm_overview}. Gli attributi vengono + restituiti in forma di maschera binaria con i valori delle costanti elencate + in tab.~\ref{tab:statx_stx_attributes}, dove si trova anche la relativa + descrizione. +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|p{8cm}|} + \hline + \textbf{Costante} & \textbf{Significato} \\ + \hline + \hline + \constd{STATX\_ATTR\_COMPRESSED}& Il file è compresso automaticamente dal + filesystem (quindi può richiedere un + maggior uso di risorse in caso di + accesso).\\ + \constd{STATX\_ATTR\_IMMUTABLE} & Il file è marcato come + \textit{immutable} e non può essere + modificato in nessun modo (vedi + sez.~\ref{sec:file_perm_overview}).\\ + \constd{STATX\_ATTR\_APPEND} & Il file è marcato come + \textit{append-only} e può essere + soltanto esteso in \textit{append} (vedi + sez.~\ref{sec:file_perm_overview}).\\ + \constd{STATX\_ATTR\_NODUMP} & Il file è marcato per essere escluso da + eventuali backup a livello di filesystem + come quelli eseguiti con il comando + \cmd{dump}.\\ + \constd{STATX\_ATTR\_ENCRYPTED} & Il file è cifrato sul filesystem ed è + necessaria una chiave di accesso per + decifrarne il contenuto.\\ + \constd{STATX\_ATTR\_AUTOMOUNT} & Il file, in questo caso in genere una + directory, è marcata come punto di + innesco per un \textit{automount}.\\ + \hline + \end{tabular} + \caption{Le costanti degli attributi addizionali restituiti in + \var{stx\_attributes}.} + \label{tab:statx_stx_attributes} +\end{table} +\item[\var{stx\_rdev\_major}, \var{stx\_rdev\_minor}] in questi campi vengono + restituiti rispettivamente \textit{major number} e \textit{minor number} del + file quando questo è un file di dispositivo (fanno le veci del campo + \var{st\_rdev} di \struct{stat}). + +\item[\var{stx\_dev\_major}, \var{stx\_dev\_minor}] in questi campi vengono + restituiti \textit{major number} e \textit{minor number} del dispositivo su + cui risiede il file (fanno le veci del campo \var{st\_dev} di \struct{stat}). +\end{basedescript} + +Di questi campi \var{stx\_mode}, \var{stx\_nlink}, \var{stx\_uid}, +\var{stx\_gid}, \var{stx\_ino}, \var{stx\_size} e \var{stx\_blocks} e quelli +relativi ai tempi ordinari dei file vengono sempre restituiti, ed il relativo +valore in \struct{statx} sovrascritto, indipendentemente dal fatto che siano +stati richiesti o no, con \var{stx\_mask} che indicherà quali sono quelli che +hanno valori effettivamente validi. + +Se un filesystem ha dei campi che non esistono o hanno valori senza +corrispondenza in un sistema unix-like, questi potranno essere restituiti con +valori fittizi ricostruiti, ad esempio usando \ids{UID} e \ids{GID} impostati +in fase di montaggio per un filesystem che non supporta gli utenti; in questi +casi il relativo bit in \var{stx\_mask} sarà comunque cancellato. In caso di +cambiamenti al file eseguiti in concorrenza a \func{statx} è possibile che +campi diversi possano avere informazioni ottenute in momenti diversi, con +valori precedenti o posteriori il cambiamento. Inoltre, se non richiesti +esplicitamente, alcuni campi possono avere valori approssimati, ad esempio in +caso di NFS, questi non vengono mai aggiornati dallo stato sul server remoto. + +Il campo \var{stx\_btime} viene restituito solo se richiesto, e si otterrà un +valore nullo (ed il relativo bit in \var{stx\_mask} cancellato) se questo non +esiste. Lo stesso vale nel caso si siano richiesti \var{stx\_rdev\_major} o +\var{stx\_rdev\_minor} ed il file non è un file di dispositivo. I campi +\var{stx\_dev\_major}, \var{stx\_dev\_minor} e \var{stx\_blksize} attengono +ad informazioni locali, e sono sempre disponibili in maniera diretta. + +% NOTE: per statx https://lwn.net/Articles/707602/ e +% https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a528d35e8bfcc521d7cb70aaf03e1bd296c8493f) + +Infine trattiamo qui altre due funzioni, \func{fexecve} e \func{execveat}, che +non attengono che in maniera indiretta all'uso dei file, ma sono comunque +legate all'interfaccia delle \textit{at-functions}. In realtà la sola +effettivamente collegata all'interfaccia delle \textit{at-functions} è la +funzione di sistema \func{execveat}, introdotta con il kernel 3.19, e per la +quale non è disponibile ancora un'interfaccia diretta nella \acr{glibc} che +però la usa (quando disponibile) per realizzare \func{fexecve}. + +L'introduzione di queste funzioni nasce dall'esigenza di verificare i +contenuti di un file eseguibile prima di eseguirlo. Fare il controllo (aprendo +il file e verificandone il contenuto) e poi eseguirlo con \func{execve} è +suscettibile alla possibilità che fra il controllo e l'esecuzione il nome del +file o di una directory sovrastante venga cambiato. + +Per mitigare il problema nello standard POSIX.1-2008 è stata introdotta la +funzione \funcd{fexecve} che consente di eseguire un programma usando un file +descriptor al posto di un \textit{pathname}; il suo prototipo è: + +\begin{funcproto}{ +\fhead{unistd.h} +\fdecl{int fexecve(int fd, char *const argv[], char *const envp[])} +\fdesc{Esegue un programma da un file descriptor.} +} + +{La funzione non ritorna in caso di successo e ritorna $-1$ per un errore, + nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EINVAL}] \param{fd} non è un file descriptor, o \param{argv} + o \param{envp} sono \val{NULL}. + \item[\errcode{ENOSYS}] il filesystem \file{proc} non è disponibile (prima + del kernel 3.19). + \end{errlist} + oltre a tutti gli errori già visti per \func{execve}.} +\end{funcproto} + +La funzione esegue il programma contenuto nel file (su cui il chiamante deve +avere il permesso di esecuzione) corrispondente a \param{fd}; questo deve +essere stato ottenuto aprendo il relativo eseguibile in sola lettura o con +\const{O\_PATH}. Questa funzione fino al kernel 3.19 veniva realizzata nella +\acr{glibc} usando il filesystem \file{/proc} per ottenere da \param{fd} il +file corrispondente in \file{/proc/self/fd/}, in maniera analoga a quanto +visto per l'esempio di fig.~\ref{fig:initfile}. + +La funzione di sistema \funcd{execveat} è stata introdotta proprio per rendere +più sicura l'esecuzione ed evitare la necessità di avere disponibile +\file{/proc} per poter usare \func{fexecve}, il suo prototipo è: + +\begin{funcproto}{ +\fhead{unistd.h} +\fdecl{int execveat(int dirfd, const char *pathname, char *const argv[], \\ +\phantom{int execveat(}char *const envp[], int flags)} +\fdesc{Esegue un programma relativo ad una directory.} +} + +{La funzione non ritorna in caso di successo e ritorna $-1$ per un errore, nel + qual caso \var{errno} assumerà, inoltre tutti gli errori già visti per + \func{execve}, uno dei valori: + \begin{errlist} + \item[\errcode{EBADF}] \param{fd} non è un file descriptor valido. + \item[\errcode{EINVAL}] \param{flags} non ha un valore valido. + \item[\errcode{ELOOP}] si è usato \const{AT\_SYMLINK\_NOFOLLOW} in + \param{flags} ma il file indicato è un link simbolico. + \item[\errcode{ENOENT}] il programma di cui si è richiesta l'esecuzione è + uno script, ma \func{dirfd} è aperto con il flag di + \textit{close-on-exec} e pertanto il programma non sarebbe accessibile + all'interprete. + \end{errlist} +} +\end{funcproto} + +La funzione segue la sintassi delle \textit{at-functions} per indicare il file +da eseguire, e per il resto si comporta esattamente con come \func{execve} (le +cui caratteristiche sono già state illustrate in +sez.~\ref{sec:proc_exec}). Diventa così possibile indicare il programma da +eseguire sia con un \textit{pathname} assoluto che relativo (usando +\const{AT\_FDCWD} come \param{dirfd}), oppure con un \textit{pathname} +relativo alla directory indicata da \param{dirfd}. In quest'ultima forma l'uso +della funzione consente estendere i vantaggi delle \textit{at-functions} anche +al caso dell'esecuzione di un programma. + +Inoltre usando, per \param{flags} il valore \const{AT\_EMPTY\_PATH}, si può +indicare direttamente il file da eseguire aprendolo e passandone il file +descriptor nell'argomento \param{dirfd}, ottenendo il comportamento di +\func{fexecve}; quest'ultima infatti è sostanzialmente equivalente +all'esecuzione di: +\includecodesnip{listati/fexecve.c} +l'unico altro valore utilizzabile per \param{flags} è +\const{AT\_SYMLINK\_NOFOLLOW}, che fa fallire la funzione con un errore di +\errval{ELOOP} se il file indicato è un link simbolico. + +Quando si usano \func{execveat} o \func{fexecve} per eseguire un programma +attraverso un file descriptor è naturale impostare sullo stesso il flag di +\textit{close-on-exec} in modo che questo venga automaticamente chiuso +all'esecuzione. Questo evita di lasciare aperto inutilmente un file descriptor +(un programma in genere non ha bisogno di avere un file aperto su se stesso), +ma soprattutto evita problemi in caso di un eventuale uso ricorsivo di queste +funzioni, in tal caso infatti, restando aperto ad ogni iterazione un ulteriore +file descriptor, si potrebbe arrivare all'esaurimento degli stessi. + +Tutto questo però non è vero quando si vuole eseguire uno script; in tal caso +infatti (si ricordi quanto detto a questo riguardo in +sez.~\ref{sec:proc_exec}) il programma che viene effettivamente messo in +esecuzione è l'interprete indicato nella riga iniziale dello script, che poi +legge ed interpreta il codice da eseguire dallo script stesso. Ma se lancia lo +script usando un file descriptor su cui è attivo il flag di +\textit{close-on-exec}, questo sarà già chiuso quando l'interprete viene posto +in esecuzione, rendendo impossibile la lettura del programma da +interpretare. + +Per questo motivo, quando ci si trova in questa situazione, \func{execveat} (e +quindi anche \func{fexecve}) eseguono un controllo preventivo e falliscono con +un errore di \errval{ENOENT}. Pertanto se si vuole eseguire uno script +passandone il file descriptor l'unica possibilità è non attivare il flag di +\textit{close-on-exec}, esponendosi però al rischio di incorrere nei problemi +accennati in precedenza. % 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: trattare i nuovi AT_flags quando e se arriveranno, vedi @@ -2463,9 +2875,11 @@ prototipo è: {La funzione ha valori di ritorno diversi a seconda dell'operazione richiesta in caso di successo mentre ritorna sempre $-1$ per un errore, nel qual caso \var{errno} assumerà valori diversi che dipendono dal tipo di operazione, - l'unico valido in generale è: + gli unici con signifiato generico sono: \begin{errlist} \item[\errcode{EBADF}] \param{fd} non è un file aperto. + \item[\errcode{EINVAL}] \param{cmd} non è un comando supportato dal kernel + corrente. \end{errlist} } \end{funcproto} @@ -2493,8 +2907,6 @@ il nome indicato nel precedente prototipo), è riportata di seguito: o \errcode{EMFILE} se il processo ha già raggiunto il massimo numero di descrittori consentito. -\itindbeg{close-on-exec} - \item[\constd{F\_DUPFD\_CLOEXEC}] ha lo stesso effetto di \const{F\_DUPFD}, ma in più attiva il flag di \textit{close-on-exec} sul file descriptor duplicato, in modo da evitare una successiva chiamata con @@ -2504,24 +2916,23 @@ il nome indicato nel precedente prototipo), è riportata di seguito: sez.~\ref{sec:intro_gcc_glibc_std}). \item[\constd{F\_GETFD}] restituisce il valore dei \textit{file descriptor - flags} di \param{fd} in caso di successo o $-1$ in caso di errore, il - terzo argomento viene ignorato. Non sono previsti errori diversi da - \errval{EBADF}. Al momento l'unico flag usato è quello di - \textit{close-on-exec}, identificato dalla costante \const{FD\_CLOEXEC}, che - serve a richiedere che il file venga chiuso nella esecuzione di una - \func{exec} (vedi sez.~\ref{sec:proc_exec}). Un valore nullo significa - pertanto che il flag non è impostato. + flags} (vedi sez.~\ref{sec:file_shared_access}) di \param{fd} in caso di + successo o $-1$ in caso di errore, il terzo argomento viene ignorato. Non + sono previsti errori diversi da \errval{EBADF}. Al momento l'unico flag + usato è quello di \textit{close-on-exec}, identificato dalla costante + \const{FD\_CLOEXEC}, che serve a richiedere che il file venga chiuso nella + esecuzione di una \func{exec} (vedi sez.~\ref{sec:proc_exec}). Un valore + nullo significa pertanto che il flag non è impostato. \item[\constd{F\_SETFD}] imposta il valore dei \textit{file descriptor flags} - al valore specificato con \param{arg}, ritorna un valore nullo in caso di - successo e $-1$ in caso di errore. Non sono previsti errori diversi da - \errval{EBADF}. Dato che l'unico flag attualmente usato è quello di - \textit{close-on-exec}, identificato dalla costante \const{FD\_CLOEXEC}, - tutti gli altri bit di \param{arg}, anche se impostati, vengono - ignorati.\footnote{questo almeno è quanto avviene fino al kernel 3.2, come - si può evincere dal codice della funzione \texttt{do\_fcntl} nel file - \texttt{fs/fcntl.c} dei sorgenti del kernel.} -\itindend{close-on-exec} + (vedi sez.~\ref{sec:file_shared_access}) al valore specificato con + \param{arg}, ritorna un valore nullo in caso di successo e $-1$ in caso di + errore. Non sono previsti errori diversi da \errval{EBADF}. Dato che l'unico + flag attualmente usato è quello di \textit{close-on-exec}, identificato + dalla costante \const{FD\_CLOEXEC}, tutti gli altri bit di \param{arg}, + anche se impostati, vengono ignorati.\footnote{questo almeno è quanto + avviene fino al kernel 3.2, come si può evincere dal codice della funzione + \texttt{do\_fcntl} nel file \texttt{fs/fcntl.c} dei sorgenti del kernel.} \item[\constd{F\_GETFL}] ritorna il valore dei \textit{file status flags} di \param{fd} in caso di successo o $-1$ in caso di errore, il terzo argomento @@ -4807,15 +5218,19 @@ con uno dei valori \const{FSETLOCKING\_INTERNAL} o % LocalWords: FIONREAD epoll FIOQSIZE side effects SAFE BYCALLER QUERY EACCES % LocalWords: EBUSY OpenBSD syncfs futimes timespec only init ESRCH kill NTPL % LocalWords: ENXIO NONBLOCK WRONLY EPERM NOATIME ETXTBSY EWOULDBLOCK PGRP SZ -% LocalWords: EFAULT capabilities GETPIPE SETPIPE RESOURCE NFSv -% LocalWords: Documentation Urlich Drepper futimesat times -% LocalWords: futimens fs Tread TMPFILE EDQUOT extN Minix UDF XFS +% LocalWords: EFAULT capabilities GETPIPE SETPIPE RESOURCE NFSv InitFile stx +% LocalWords: Documentation Urlich Drepper futimesat times FullWrite major +% LocalWords: futimens fs Tread TMPFILE EDQUOT extN Minix UDF XFS mask all' % LocalWords: shmem Btrfs ubifs tmpfile fchmod fchown fsetxattr fchdir PF -% LocalWords: fstatfs SIGTTIN EDESTADDRREQ datagram connect seal pag +% LocalWords: fstatfs SIGTTIN EDESTADDRREQ datagram connect seal pag l'I INO % LocalWords: dirty execveat execve scandirat statx AUTOMOUNT automount DAC -% LocalWords: wrapper EMPTY olddirfd oldpath newdirfd newpath capability +% LocalWords: wrapper EMPTY olddirfd oldpath newdirfd newpath capability ino % LocalWords: SEARCH flink choot oldirfd NOREPLACE EXCHANGE WHITEOUT union -% LocalWords: renamat syscall whiteout overlay filesytem Live +% LocalWords: renamat syscall whiteout overlay filesytem Live nell' sull' +% LocalWords: statbuf statxbuf IFMT nlink atime mtime fexecve argv envp +% LocalWords: blocks STATS btime RESERVED ctime ATTR dev ENOSYS +% LocalWords: timestamp attributes COMPRESSED immutable NODUMP +% LocalWords: dump ENCRYPTED rdev all'I dell'I %%% Local Variables: %%% mode: latex