X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileio.tex;h=40dcd9f94ee29c3c3206ccca0eefd415b474cdfd;hp=54443481fe773216c8ea169e59d347bc818ac3ea;hb=5da5870ef70a2b793118d14ec547a293927c0d3c;hpb=cda41b2445832d1c5f364ba501d5ef06b78f6aa3 diff --git a/fileio.tex b/fileio.tex index 5444348..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 @@ -2708,13 +2714,13 @@ 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 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}. +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 @@ -2748,8 +2754,8 @@ 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 maniera analoga a quanto visto per l'esempio di -fig.~\ref{fig:initfile}. +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 @@ -2779,28 +2785,50 @@ più sicura l'esecuzione ed evitare la necessità di avere disponibile \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}; è -pertanto possibile indicare il programma da eseguire sia con un -\textit{pathname} assoluto che relativo, ed anche con un \textit{pathname} -relativo alla directory indicata da \param{dirfd}. Inoltre usando per -\param{flags} il valore \const{AT\_EMPTY\_PATH} si può indicare direttamente -il file con il file descriptor \param{dirfd} ottenendo il comportamento di -\func{fexecve}, che è equivalnente 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. +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 è opportuno impostare sempre sullo stesso il -flag di \textit{close-on-exec}, in modo che questo venga automaticamente -chiuso all'esecuzione. Questo evita di consumare inutilmente un file -descriptor (un programma non ha bisogno di un riferimento a se stesso), ma -soprattutto evita problemi in caso di un eventuale uso ricorsivo di queste -funzioni che potrebbe portare, restando aperto ogni volta un ulteriore file -descriptor, all'esaurimento degli stessi. - - - +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 @@ -2847,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} @@ -2877,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 @@ -2888,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