X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=filedir.tex;h=0b958c28b0a7ae3b5fd2aa6ccd3787c4dc5cecb2;hp=7973c78c70fb656f2cea3340ae53858b7d96d135;hb=40b56f315688ca3a539b442f060d2b5ea866920b;hpb=5d7fe3ee9e2509853d2d06902b6b503680135641 diff --git a/filedir.tex b/filedir.tex index 7973c78..0b958c2 100644 --- a/filedir.tex +++ b/filedir.tex @@ -961,7 +961,7 @@ argomento che deve essere specificato quando li si usano è \param{target}; mount}. Lo scopo dell'opzione è ottenere che tutti i successivi \textit{bind mount} ottenuti da un \textit{mount point} così marcato siano di tipo \textit{shared} e vengano inseriti nello stesso \textit{mount peer - group} in modo da ``\textsl{condivere}'' ogni ulteriore operazione di + group} in modo da ``\textsl{condividere}'' ogni ulteriore operazione di montaggio o smontaggio. Con questa opzione le operazioni di montaggio e smontaggio effettuate al di sotto di uno \textit{shared mount} vengono automaticamente ``\textsl{propagate}'' a tutti gli altri membri del @@ -1451,9 +1451,9 @@ fanno comunque riferimento allo stesso \textit{inode} e quindi tutti otterranno lo stesso file. Quando si vuole aggiungere ad una directory una voce che faccia riferimento ad -un file già esistente nella modalità appena descritta, per ottenere quello che -viene denominato ``\textsl{collegamento diretto}'' (o \textit{hard link}), si -deve usare la funzione di sistema \funcd{link}, il cui prototipo è: +un file già esistente come appena descritto, per ottenere quello che viene +denominato ``\textsl{collegamento diretto}'' (o \textit{hard link}), si deve +usare la funzione di sistema \funcd{link}, il cui prototipo è: \begin{funcproto}{ \fhead{unistd.h} @@ -1469,19 +1469,22 @@ deve usare la funzione di sistema \funcd{link}, il cui prototipo è: (il numero massimo è specificato dalla variabile \const{LINK\_MAX}, vedi sez.~\ref{sec:sys_limits}). \item[\errcode{EPERM}] il filesystem che contiene \param{oldpath} e - \param{newpath} non supporta i collegamenti diretti, è una directory o non - si rispettano i criteri per i \textit{protected hardlink}.\footnotemark + \param{newpath} non supporta i collegamenti diretti, è una directory o per + \param{oldpath} non si rispettano i criteri per i \textit{protected + hardlink}.\footnotemark \item[\errcode{EXDEV}] i file \param{oldpath} e \param{newpath} non fanno riferimento ad un filesystem montato sullo stesso \textit{mount point}. - \end{errlist} ed inoltre \errval{EACCES}, \errval{EFAULT}, \errval{EIO}, - \errval{ELOOP}, \errval{ENAMETOOLONG}, \errval{ENOENT}, \errval{ENOMEM}, - \errval{ENOSPC}, \errval{ENOTDIR}, \errval{EROFS} nel loro significato - generico.} + \end{errlist} ed inoltre \errval{EACCES}, \errval{EDQUOT}, \errval{EFAULT}, + \errval{EIO}, \errval{ELOOP}, \errval{ENAMETOOLONG}, \errval{ENOENT}, + \errval{ENOMEM}, \errval{ENOSPC}, \errval{ENOTDIR}, \errval{EROFS} nel loro + significato generico.} \end{funcproto} \footnotetext{i \textit{protected hardlink} sono una funzionalità di - protezione introdotta con il kernel 3.16 (vedi sez..} + protezione introdotta con il kernel 3.16 (si veda + sez.~\ref{sec:procadv_security_misc} per i dettagli) che limita la capacità + di creare un \textit{hard link} ad un file qualunque.} La funzione crea in \param{newpath} un collegamento diretto al file indicato da \param{oldpath}. Per quanto detto la creazione di un nuovo collegamento @@ -1503,19 +1506,17 @@ riferimento ad essi all'interno dello stesso \textit{mount point}.\footnote{si tenga presente infatti, come detto in sez.~\ref{sec:filesystem_mounting}, che a partire dal kernel 2.4 uno stesso filesystem può essere montato più volte su directory diverse.} - La funzione inoltre opera sia sui file ordinari che sugli altri oggetti del filesystem, con l'eccezione delle directory. In alcune versioni di Unix solo l'amministratore è in grado di creare un collegamento diretto ad un'altra directory: questo viene fatto perché con una tale operazione è possibile creare dei \textit{loop} nel filesystem (vedi fig.~\ref{fig:file_link_loop}) -che molti programmi non sono in grado di gestire e la cui rimozione -diventerebbe piuttosto complicata.\footnote{in genere per questo tipo di - errori occorre eseguire il programma \cmd{fsck} per riparare il filesystem, - in quanto in caso di \textit{loop} la directory creata non sarebbe vuota e - non si potrebbe più rimuoverla.} +la cui rimozione diventerebbe piuttosto complicata.\footnote{occorrerebbe + infatti eseguire il programma \cmd{fsck} per riparare il filesystem, perché + in caso di \textit{loop} la directory non potrebbe essere più svuotata, + contenendo comunque se stessa, e quindi non potrebbe essere rimossa.} -Data la pericolosità di questa operazione, e vista che i collegamenti +Data la pericolosità di questa operazione, e visto che i collegamenti simbolici (che tratteremo a breve) ed i \textit{bind mount} (già visti in sez.~\ref{sec:filesystem_mounting}) possono fornire la stessa funzionalità senza questi problemi, nel caso di Linux questa capacità è stata completamente @@ -1597,6 +1598,8 @@ sistema che permette di creare un nuovo collegamento simbolico è {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}] o non si hanno i permessi sulla directory in cui + creare il \textit{link}. \item[\errcode{EEXIST}] esiste già un file \param{newpath}. \item[\errcode{ENOENT}] una componente di \param{newpath} non esiste o \param{oldpath} è una stringa vuota. @@ -1604,11 +1607,12 @@ sistema che permette di creare un nuovo collegamento simbolico è supporta i collegamenti simbolici. \item[\errcode{EROFS}] \param{newpath} è su un filesystem montato in sola lettura. - \end{errlist} ed inoltre \errval{EACCES}, \errval{EFAULT}, \errval{EIO}, + \end{errlist} ed inoltre \errval{EDQUOT}, \errval{EFAULT}, \errval{EIO}, \errval{ELOOP}, \errval{ENAMETOOLONG}, \errval{ENOMEM}, \errval{ENOSPC} e \errval{ENOTDIR} nel loro significato generico.} \end{funcproto} + La funzione crea un nuovo collegamento simbolico \param{newpath} che fa riferimento ad \param{oldpath}. Si tenga presente che la funzione non effettua nessun controllo sull'esistenza di un file di nome \param{oldpath}, @@ -1616,7 +1620,30 @@ ma si limita ad inserire il \textit{pathname} nel collegamento simbolico. Pertanto un collegamento simbolico può anche riferirsi ad un file che non esiste ed in questo caso si ha quello che viene chiamato un \itindex{dangling~link} \textit{dangling link}, letteralmente un -\index{collegamento!ciondolante} ``\textsl{collegamento ciondolante}''. +\index{collegamento!ciondolante} ``\textsl{collegamento ciondolante}''. Ad +esempio possiamo usare il comando \cmd{ln} per creare un collegamento +simbolico nella nostra directory con: +\begin{Console} +piccardi@hain:~/gapil$ \textbf{ln -s /tmp/tmp_file symlink} +\end{Console} +%$ +e questo avrà successo anche se \file{/tmp/tmp\_file} non esiste: +\begin{Console} +piccardi@hain:~/gapil$ \textbf{ls symlink} +symlink +\end{Console} +%$ +ma questo può generare confusione, perché accedendo in lettura a +\file{symlink}, ad esempio con \cmd{cat}, otterremmo: +\begin{Console} +piccardi@hain:~/gapil$ \textbf{cat symlink} +cat: symlink: No such file or directory +\end{Console} +%$ +con un errore che può sembrare sbagliato, dato che \cmd{ls} ci ha mostrato in +precedenza l'esistenza di \file{symlink}. Se invece andassimo a scrivere su +\file{symlink}, l'effetto sarebbe quello di ottenere la creazione di +\file{/tmp/tmp\_file} (che a quel punto verrebbe creato) senza errori. Come accennato i collegamenti simbolici sono risolti automaticamente dal kernel all'invocazione delle varie \textit{system call}. In @@ -1669,6 +1696,13 @@ funzione che restituisce il file descriptor (normalmente la \func{open}, vedi sez.~\ref{sec:file_open_close}) e tutte le operazioni seguenti fanno riferimento solo a quest'ultimo. +Si tenga anche presente che a partire dal kernel 3.16, se si abilita la +funzionalità dei \textit{protected symlinks} (attiva di default in tutte le +distribuzioni più recenti) la risoluzione dei nomi attraverso un collegamento +simbolico può fallire per una serie di restrizione di sicurezza aggiuntive +imposte dal meccanismo (si consulti sez.~\ref{sec:procadv_security_misc} per i +dettagli del meccanismo). + Dato che, come indicato in tab.~\ref{tab:file_symb_effect}, funzioni come la \func{open} seguono i collegamenti simbolici, occorrono funzioni apposite per accedere alle informazioni del collegamento invece che a quelle del file a cui @@ -1677,30 +1711,32 @@ simbolico si usa la funzione di sistema \funcd{readlink}, il cui prototipo è: \begin{funcproto}{ \fhead{unistd.h} -\fdecl{int readlink(const char *path, char *buff, size\_t size)} +\fdecl{int readlink(const char *pathname, char *buff, size\_t size)} \fdesc{Legge il contenuto di un collegamento simbolico.} } {La funzione ritorna il numero di caratteri letti dentro \param{buff} in caso di successo e $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} - \item[\errcode{EINVAL}] \param{path} non è un collegamento simbolico + \item[\errcode{EACCES}] non si hanno i permessi di attraversamento di una + delle directory del pathname + \item[\errcode{EINVAL}] \param{pathname} non è un collegamento simbolico o \param{size} non è positiva. - \end{errlist} ed inoltre \errval{EACCES}, \errval{EFAULT}, \errval{EIO}, - \errval{ELOOP}, \errval{ENAMETOOLONG}, \errval{ENOENT}, \errval{ENOMEM} e - \errval{ENOTDIR} nel loro significato generico.} + \end{errlist} ed inoltre \errval{EFAULT}, \errval{EIO}, \errval{ELOOP}, + \errval{ENAMETOOLONG}, \errval{ENOENT}, \errval{ENOMEM} e \errval{ENOTDIR} + nel loro significato generico.} \end{funcproto} La funzione legge il \textit{pathname} a cui fa riferimento il collegamento -simbolico indicato dall'argomento \param{path} scrivendolo sul -buffer \param{buff} di dimensione \param{size}. Si tenga presente che la -funzione non termina la stringa con un carattere nullo e che se questa è -troppo lunga la tronca alla dimensione specificata da \param{size} per evitare -di sovrascrivere oltre le dimensioni del buffer. +simbolico indicato dall'argomento \param{pathname} scrivendolo sul buffer +\param{buff} di dimensione \param{size}. Si tenga presente che la funzione non +termina la stringa con un carattere nullo e che se questa è troppo lunga la +tronca alla dimensione specificata da \param{size} per evitare di scrivere +dati oltre le dimensioni del buffer. \begin{figure}[htb] \centering - \includegraphics[width=8.5cm]{img/link_loop} + \includegraphics[width=8cm]{img/link_loop} \caption{Esempio di loop nel filesystem creato con un collegamento simbolico.} \label{fig:file_link_loop} @@ -1711,68 +1747,41 @@ alle directory è che questi possono creare dei \textit{loop} nella risoluzione dei nomi che non possono essere eliminati facilmente. Invece è sempre possibile, ed in genere anche molto utile, creare un collegamento simbolico ad una directory, anche se in questo caso si potranno ottenere anche dei -\textit{loop}. La situazione è illustrata in fig.~\ref{fig:file_link_loop}, -che riporta la struttura della directory \file{/boot}. Come si vede si è -creato al suo interno un collegamento simbolico che punta di nuovo a +\textit{loop}. + +La situazione è illustrata in fig.~\ref{fig:file_link_loop}, che riporta la +struttura della directory \file{/boot}. Come si vede si è creato al suo +interno un collegamento simbolico che punta di nuovo a \file{/boot}.\footnote{il \textit{loop} mostrato in - fig.~\ref{fig:file_link_loop} è stato usato per poter permettere a - \cmd{grub} (un bootloader in grado di leggere direttamente da vari - filesystem il file da lanciare come sistema operativo) di vedere i file - contenuti nella directory \file{/boot} con lo stesso \textit{pathname} con - cui verrebbero visti dal sistema operativo, anche se essi si trovano, come - accade spesso, su una partizione separata (che \cmd{grub} all'avvio vedrebbe - come \file{/}).} - -Questo però può causare problemi per tutti quei programmi che effettuano la -scansione di una directory senza tener conto dei collegamenti simbolici, ad -esempio se lanciassimo un comando del tipo \code{grep -r linux *}, il loop -nella directory porterebbe il comando ad esaminare \file{/boot}, -\file{/boot/boot}, \file{/boot/boot/boot} e così via. + fig.~\ref{fig:file_link_loop} è stato usato per poter permettere a al + \textit{bootloader} \cmd{grub} di vedere i file contenuti nella directory + \file{/boot} con lo stesso \textit{pathname} con cui verrebbero visti dal + sistema operativo, anche quando si trovano, come accade spesso, su una + partizione separata (che \cmd{grub} all'avvio vedrebbe come \file{/}).} Un +\textit{loop} di di questo tipo però può causare problemi per tutti i +programmi che effettuano la scansione di una directory, e ad esempio se +lanciassimo un comando come \code{grep -r linux *}, il \textit{loop} nella +directory porterebbe ad esaminare \file{/boot}, \file{/boot/boot}, +\file{/boot/boot/boot} e così via. Per questo motivo il kernel e le librerie prevedono che nella risoluzione di un \textit{pathname} possano essere seguiti fino ad un certo numero massimo di collegamenti simbolici, il cui valore limite è specificato dalla costante -\constd{MAXSYMLINKS}. Qualora questo limite venga superato viene generato un -errore ed \var{errno} viene impostata al valore \errcode{ELOOP}, che nella -quasi totalità dei casi indica appunto che si è creato un collegamento -simbolico che fa riferimento ad una directory del suo stesso -\textit{pathname}. - -Un altro punto da tenere sempre presente è che, come abbiamo accennato, un -collegamento simbolico può fare riferimento anche ad un file che non esiste; -ad esempio possiamo usare il comando \cmd{ln} per creare un collegamento -simbolico nella nostra directory con: -\begin{Console} -piccardi@hain:~/gapil$ \textbf{ln -s /tmp/tmp_file symlink} -\end{Console} -%$ -e questo avrà successo anche se \file{/tmp/tmp\_file} non esiste: -\begin{Console} -piccardi@hain:~/gapil$ \textbf{ls symlink} -symlink -\end{Console} -%$ -ma questo può generare confusione, perché accedendo in sola lettura a -\file{symlink}, ad esempio con \cmd{cat}, otterremmo un errore: -\begin{Console} -piccardi@hain:~/gapil$ \textbf{cat symlink} -cat: symlink: No such file or directory -\end{Console} -%$ -con un errore che può sembrare sbagliato, dato che \cmd{ls} ci ha mostrato -l'esistenza di \file{symlink}, se invece scrivessimo su \file{symlink} -otterremmo la creazione di \file{/tmp/tmp\_file} senza errori. +\constd{MAXSYMLINKS}. Se il limite viene superato si ha un errore ed +\var{errno} viene impostata al valore \errcode{ELOOP}, che nella quasi +totalità dei casi indica appunto che si è creato un collegamento simbolico che +fa riferimento ad una directory del suo stesso \textit{pathname}. \itindend{symbolic~link} \index{collegamento!simbolico|)} Un'altra funzione relativa alla gestione dei nomi dei file, anche se a prima -vista parrebbe riguardare un argomento completamente diverso, è quella che per -la cancellazione di un file. In realtà una \textit{system call} che serva -proprio a cancellare un file non esiste neanche perché, come accennato in +vista parrebbe riguardare un argomento completamente diverso, è quella per la +cancellazione di un file. In realtà una \textit{system call} che serva proprio +a cancellare un file non esiste neanche perché, come accennato in sez.~\ref{sec:file_filesystem}, quando in un sistema unix-like si richiede la -rimozione di un file quella che si va a cancellare è soltanto la voce che +rimozione di un file, quello che si va a cancellare è soltanto la voce che referenzia il suo \textit{inode} all'interno di una directory. La funzione di sistema che consente di effettuare questa operazione, il cui @@ -1788,13 +1797,16 @@ nome come si può notare ha poco a che fare con il concetto di rimozione, è nel qual caso \var{errno} assumerà uno dei valori:\footnotemark \begin{errlist} \item[\errcode{EACCES}] non si ha il permesso di scrittura sulla directory - che contiene \param{pathname} o di attraversamento di una delle directory - superiori. + che contiene \param{pathname} o quello di attraversamento per una delle + directory superiori. + \item[\errcode{EBUSY}] \param{pathname} non può essere rimosso perché è in + uso da parte del sistema (in particolare per i cosiddetti \textit{silly + renames} di NFS). \item[\errcode{EISDIR}] \param{pathname} si riferisce ad una directory. \item[\errcode{EPERM}] il filesystem non consente l'operazione, o la directory che contiene \param{pathname} ha lo \textit{sticky bit} e non si - è il proprietario o non si hanno privilegi amministrativi. + è il proprietario del file o non si hanno privilegi amministrativi. \end{errlist} ed inoltre \errval{EFAULT}, \errval{EIO}, \errval{ELOOP}, \errval{ENOENT}, \errval{ENOMEM}, \errval{ENOTDIR}, \errval{EROFS} nel loro significato generico.} @@ -1811,55 +1823,60 @@ nome come si può notare ha poco a che fare con il concetto di rimozione, è La funzione elimina il nome specificato dall'argomento \param{pathname} nella directory che lo contiene e decrementa il numero di riferimenti nel relativo -\textit{inode}.\footnote{come per \func{link} queste due operazioni sono - effettuate all'interno della \textit{system call} in maniera atomica.} Nel -caso di socket, \textit{fifo} o file di dispositivo rimuove il nome, ma come -per i file normali i processi che hanno aperto uno di questi oggetti possono -continuare ad utilizzarli. Nel caso di cancellazione di un collegamento -simbolico, che consiste solo nel rimando ad un altro file, questo viene -immediatamente eliminato. +\textit{inode}; come per \func{link} queste due operazioni sono effettuate +all'interno della \textit{system call} in maniera atomica rispetto ai +processi. + +Si ricordi che, anche se se ne è rimosso il nome, un file viene realmente +cancellato soltanto quando il numero di collegamenti mantenuto +nell'\textit{inode} diventa nullo; solo allora l'\textit{inode} viene +disallocato e lo spazio che il file occupava sul disco viene liberato. + +Si tenga presente comunque che a questo si aggiunge sempre un'ulteriore +condizione e cioè che non ci siano processi che stiano ancora lavorando sul il +file. Come vedremo in sez.~\ref{sec:file_unix_interface} il kernel una tabella +di tutti file aperti da ciascun processo, che a sua volta contiene i +riferimenti agli \textit{inode} ad essi relativi. Prima di procedere alla +cancellazione dello spazio occupato su disco dal contenuto di un file il +kernel controlla anche questa tabella, per verificare che anche in essa non ci +sia più nessun riferimento all'\textit{inode} in questione, assicurandosi con +questo che nessun processo stia ancora usando il file. + +Nel caso di socket, \textit{fifo} o file di dispositivo la funzione rimuove il +nome, e come per i file normali i processi che hanno aperto uno di questi +oggetti possono continuare ad utilizzarli. Nel caso di cancellazione di un +\textit{link} simbolico, che consiste solo nel rimando ad un altro file, +questo viene immediatamente eliminato e non sarà più utilizzabile. Per cancellare una voce in una directory è necessario avere il permesso di scrittura su di essa, dato che si va a rimuovere una voce dal suo contenuto, e il diritto di esecuzione/attraversamento sulla directory che la contiene (affronteremo in dettaglio l'argomento dei permessi di file e directory in -sez.~\ref{sec:file_access_control}). Se inoltre lo \textit{sticky bit} (vedi -sez.~\ref{sec:file_special_perm}) è impostato occorrerà anche essere -proprietari del file o proprietari della directory o avere i privilegi di -amministratore. - -Si ricordi inoltre che anche se se ne è rimosso il nome da una directory, un -file non viene eliminato dal disco fintanto che tutti i riferimenti ad esso -sono stati cancellati: solo quando il numero di collegamenti mantenuto -nell'\textit{inode} diventa nullo, questo viene disallocato e lo spazio -occupato su disco viene liberato. Si tenga presente comunque che a questo si -aggiunge sempre un'ulteriore condizione e cioè che non ci siano processi che -abbiano il suddetto file aperto.\footnote{come vedremo in - sez.~\ref{sec:file_unix_interface} il kernel mantiene anche una tabella dei - file aperti nei vari processi, che a sua volta contiene i riferimenti agli - \textit{inode} ad essi relativi; prima di procedere alla cancellazione dello - spazio occupato su disco dal contenuto di un file il kernel controlla anche - questa tabella, per verificare che anche in essa non ci sia più nessun - riferimento all'\textit{inode} in questione.} - -Questa caratteristica del sistema può essere usata per essere sicuri di non -lasciare file temporanei su disco in caso di crash di un programma. La tecnica -è quella di aprire un nuovo file e chiamare \func{unlink} su di esso subito +sez.~\ref{sec:file_access_control}). Se inoltre per la directory è impostato +lo \textit{sticky bit} (vedi sez.~\ref{sec:file_special_perm}), occorrerà +anche essere proprietari del file o proprietari della directory o avere i +privilegi di amministratore. + +Questa caratteristica del sistema, che consente di usare un file anche se lo +si è ``cancellato'', può essere usata per essere sicuri di non lasciare file +temporanei su disco in caso di uscita imprevista di un programma. La tecnica è +quella di aprire un nuovo file e chiamare \func{unlink} su di esso subito dopo, in questo modo il contenuto del file sarà sempre disponibile all'interno del processo attraverso il suo file descriptor (vedi sez.~\ref{sec:file_fd}), -ma non ne resta traccia in nessuna directory, e lo spazio occupato su disco -viene immediatamente rilasciato alla conclusione del processo, quando tutti i -file vengono chiusi. +ma non ne resterà traccia in nessuna directory, inoltre lo spazio occupato su +disco verrà immediatamente rilasciato alla conclusione del processo, quando +tutti i file vengono chiusi. Al contrario di quanto avviene con altri Unix, in Linux non è possibile usare -la funzione \func{unlink} sulle directory, nel qual caso si otterrebbe un +la funzione \func{unlink} sulle directory, che in tal caso fallisce con un errore di \errcode{EISDIR}. Per cancellare una directory si deve usare la apposita funzione di sistema \func{rmdir} (che vedremo in sez.~\ref{sec:file_dir_creat_rem}), oppure la funzione \func{remove}. + Quest'ultima è la funzione prevista dallo standard ANSI C per effettuare una -cancellazione generica di un file o di una directory e funziona anche per i -sistemi operativo che non supportano gli \textit{hard link}. Nei sistemi -unix-like \funcd{remove} è equivalente ad usare in maniera trasparente +cancellazione generica di un file o di una directory e viene usata in generale +anche per i sistemi operativi che non supportano gli \textit{hard link}. Nei +sistemi unix-like \funcd{remove} è equivalente ad usare in maniera trasparente \func{unlink} per i file ed \func{rmdir} per le directory; il suo prototipo è: \begin{funcproto}{ @@ -1873,13 +1890,15 @@ unix-like \funcd{remove} è equivalente ad usare in maniera trasparente \func{unlink} e \func{rmdir}.} \end{funcproto} -La funzione utilizza la funzione \func{unlink} per cancellare i file e la -funzione \func{rmdir} (vedi sez.~\ref{sec:file_dir_creat_rem}) per cancellare -le directory.\footnote{questo vale usando la \acr{glibc}; nella \acr{libc4} e - nella \acr{libc5} la funzione \func{remove} era un semplice alias alla - funzione \func{unlink} e quindi non poteva essere usata per le directory.} -Si tenga presente che per alcune implementazioni del protocollo NFS utilizzare -questa funzione può comportare la scomparsa di file ancora in uso. +La funzione utilizza la funzione \func{unlink} per cancellare i file (e si +applica anche a link simbolici, socket, \textit{fifo} e file di dispositivo) e +la funzione \func{rmdir} (vedi sez.~\ref{sec:file_dir_creat_rem}) per +cancellare le directory.\footnote{questo vale usando la \acr{glibc}; nella + \acr{libc4} e nella \acr{libc5} la funzione \func{remove} era un semplice + alias alla funzione \func{unlink} e quindi non poteva essere usata per le + directory.} Si tenga presente che, per alcune limitazioni del protocollo +NFS, utilizzare questa funzione su file che usano questo filesystem di rete +può comportare la scomparsa di file ancora in uso. Infine per cambiare nome ad un file o a una directory si usa la funzione di sistema \funcd{rename},\footnote{la funzione è definita dallo standard ANSI C, @@ -1894,9 +1913,9 @@ sistema \funcd{rename},\footnote{la funzione è definita dallo standard ANSI C, {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{EACCESS}] non c'è permesso di scrivere nelle directory + \item[\errcode{EACCESS}] manca il permesso di scrittura sulle directory contenenti \param{oldpath} e \param{newpath} o di attraversare - quelle dei loro \textit{pathname} o di scrivere su \param{newpath} + il loro \textit{pathname} o di scrivere su \param{newpath} se questa è una directory. \item[\errcode{EBUSY}] o \param{oldpath} o \param{newpath} sono in uso da parte di qualche processo (come directory di lavoro o come radice) o del @@ -2075,6 +2094,12 @@ nella directory genitrice, questo significa che \textit{pathname} terminanti in ``\file{.}'' e ``\file{..}'' anche se validi in altri contesti, causeranno il fallimento della funzione. +Inoltre per eseguire la cancellazione, oltre ad essere vuota, occorre anche +che la directory non sia utilizzata, questo vuol dire anche che non deve +essere la directory di lavoro (vedi sez.~\ref{sec:file_work_dir}) o la +directory radice (vedi sez.~\ref{sec:file_chroot}) di nessun processo, od +essere utilizzata come \textit{mount point}. + Se la directory cancellata risultasse aperta in qualche processo per una lettura dei suoi contenuti (vedi sez.~\ref{sec:file_dir_read}), pur scomparendo dal filesystem e non essendo più possibile accedervi o crearvi @@ -2525,7 +2550,7 @@ estensione\footnote{la \acr{glibc}, a partire dalla versione 2.1, effettua \func{versionsort}, che ordina i nomi tenendo conto del numero di versione, cioè qualcosa per cui \texttt{file10} viene comunque dopo \texttt{file4}. -\begin{figure}[!htbp] +\begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{\codesamplewidth} \includecodesample{listati/my_ls.c} @@ -2560,11 +2585,11 @@ dati ad esso relativi, per poi provvedere (\texttt{\small 27}) a stampare il nome del file e la dimensione riportata in \var{data}. Dato che la funzione verrà chiamata all'interno di \myfunc{dir\_scan} per ogni -voce presente questo è sufficiente a stampare la lista completa dei file e +voce presente, questo è sufficiente a stampare la lista completa dei file e delle relative dimensioni. Si noti infine come si restituisca sempre 0 come valore di ritorno per indicare una esecuzione senza errori. -\begin{figure}[!htbp] +\begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{\codesamplewidth} \includecodesample{listati/dir_scan.c} @@ -2602,7 +2627,7 @@ voce valida, cioè un puntatore diverso da \val{NULL}, si esegue caso sarà \code{do\_ls}), ritornando con un codice di errore (\texttt{\small 28}) qualora questa presenti una anomalia, identificata da un codice di ritorno negativo. Una volta terminato il ciclo la funzione si conclude con la -chiusura (\texttt{\small 32}) dello \textit{stream}\footnote{nel nostro caso, +chiusura (\texttt{\small 31}) dello \textit{stream}\footnote{nel nostro caso, uscendo subito dopo la chiamata, questo non servirebbe, in generale però l'operazione è necessaria, dato che la funzione può essere invocata molte volte all'interno dello stesso processo, per cui non chiudere i @@ -2618,14 +2643,14 @@ chiusura (\texttt{\small 32}) dello \textit{stream}\footnote{nel nostro caso, \index{directory~di~lavoro|(} Come accennato in sez.~\ref{sec:proc_fork} a ciascun processo è associata una -directory nel filesystem,\footnote{questa viene mantenuta all'interno dei dati - della sua \kstruct{task\_struct} (vedi fig.~\ref{fig:proc_task_struct}), più - precisamente nel campo \texttt{pwd} della sotto-struttura - \kstruct{fs\_struct}.} che è chiamata \textsl{directory corrente} o -\textsl{directory di lavoro} (in inglese \textit{current working directory}). -La directory di lavoro è quella da cui si parte quando un \textit{pathname} è -espresso in forma relativa, dove il ``\textsl{relativa}'' fa riferimento -appunto a questa directory. +directory nell'albero dei file,\footnote{questa viene mantenuta all'interno + dei dati della sua \kstruct{task\_struct} (vedi + fig.~\ref{fig:proc_task_struct}), più precisamente nel campo \texttt{pwd} + della sotto-struttura \kstruct{fs\_struct}.} che è chiamata +\textsl{directory corrente} o \textsl{directory di lavoro} (in inglese +\textit{current working directory}). La directory di lavoro è quella da cui +si parte quando un \textit{pathname} è espresso in forma relativa, dove il +``\textsl{relativa}'' fa riferimento appunto a questa directory. Quando un utente effettua il login, questa directory viene impostata alla \textit{home directory} del suo account. Il comando \cmd{cd} della shell @@ -2635,13 +2660,12 @@ resta la stessa quando viene creato un processo figlio (vedi sez.~\ref{sec:proc_fork}), la directory di lavoro della shell diventa anche la directory di lavoro di qualunque comando da essa lanciato. -Dato che è il kernel che tiene traccia per ciascun processo -dell'\textit{inode} della directory di lavoro, per ottenerne il -\textit{pathname} occorre usare una apposita funzione, -\funcd{getcwd},\footnote{con Linux \func{getcwd} è una \textit{system call} - dalla versione 2.1.9, in precedenza il valore doveva essere ottenuto tramite - il filesystem \texttt{/proc} da \procfile{/proc/self/cwd}.} il cui prototipo -è: +Dato che è il kernel che tiene traccia dell'\textit{inode} della directory di +lavoro di ciascun processo, per ottenerne il \textit{pathname} occorre usare +una apposita funzione, \funcd{getcwd},\footnote{con Linux \func{getcwd} è una + \textit{system call} dalla versione 2.1.9, in precedenza il valore doveva + essere ottenuto tramite il filesystem \texttt{/proc} da + \procfile{/proc/self/cwd}.} il cui prototipo è: \begin{funcproto}{ \fhead{unistd.h} @@ -2660,7 +2684,8 @@ dell'\textit{inode} della directory di lavoro, per ottenerne il \item[\errcode{ERANGE}] l'argomento \param{size} è più piccolo della lunghezza del \textit{pathname}. \end{errlist} - ed inoltre \errcode{EFAULT} nel suo significato generico.} + ed inoltre \errcode{EFAULT} ed \errcode{ENOMEM} nel loro significato + generico.} \end{funcproto} La funzione restituisce il \textit{pathname} completo della directory di @@ -2671,13 +2696,19 @@ buffer deve essere sufficientemente largo da poter contenere il esso ecceda le dimensioni specificate con \param{size} la funzione restituisce un errore. -Si può anche specificare un puntatore nullo come -\param{buffer},\footnote{questa è un'estensione allo standard POSIX.1, - supportata da Linux e dalla \acr{glibc}.} nel qual caso la stringa sarà -allocata automaticamente per una dimensione pari a \param{size} qualora questa -sia diversa da zero, o della lunghezza esatta del \textit{pathname} -altrimenti. In questo caso ci si deve ricordare di disallocare la stringa con -\func{free} una volta cessato il suo utilizzo. +A partire dal kernel Linux 2.6.36 il nome può avere come prefisso la stringa +\texttt{(unreachable)} se la directory di lavoro resta fuori dalla directory +radice del processo dopo un \func{chroot} (torneremo su questi argomenti in +sez.~\ref{sec:file_chroot}); pertanto è sempre opportuno controllare il primo +carattere della stringa restituita dalla funzione per evitare di interpreare +mare un \textit{pathname} irraggiungibile. + +Come estensione allo standard POSIX.1, supportata da Linux e dalla +\acr{glibc}, si può anche specificare un puntatore nullo come \param{buffer} +nel qual caso la stringa sarà allocata automaticamente per una dimensione pari +a \param{size} qualora questa sia diversa da zero, o della lunghezza esatta +del \textit{pathname} altrimenti. In questo caso ci si deve ricordare di +disallocare la stringa con \func{free} una volta cessato il suo utilizzo. Un uso comune di \func{getcwd} è quello di salvarsi la directory di lavoro all'avvio del programma per poi potervi tornare in un tempo successivo, un @@ -2696,15 +2727,15 @@ detto che il buffer sia sufficiente a contenere il nome del file, e questa è la ragione principale per cui questa funzione è deprecata, e non la tratteremo. Una seconda funzione usata per ottenere la directory di lavoro è -\funcm{get\_current\_dir\_name},\footnote{la funzione è una estensione GNU e - presente solo nella \acr{glibc}.} che non prende nessun argomento ed è -sostanzialmente equivalente ad una \code{getcwd(NULL, 0)}, con la differenza -che se disponibile essa ritorna il valore della variabile di ambiente -\envvar{PWD}, che essendo costruita dalla shell può contenere un -\textit{pathname} comprendente anche dei collegamenti simbolici. Usando -\func{getcwd} infatti, essendo il \textit{pathname} ricavato risalendo -all'indietro l'albero della directory, si perderebbe traccia di ogni passaggio -attraverso eventuali collegamenti simbolici. +\funcm{get\_current\_dir\_name} (la funzione è una estensione GNU e presente +solo nella \acr{glibc}) che non prende nessun argomento ed è sostanzialmente +equivalente ad una \code{getcwd(NULL, 0)}, con la differenza che se +disponibile essa ritorna il valore della variabile di ambiente \envvar{PWD}, +che essendo costruita dalla shell può contenere un \textit{pathname} +comprendente anche dei collegamenti simbolici. Usando \func{getcwd} infatti, +essendo il \textit{pathname} ricavato risalendo all'indietro l'albero della +directory, si perderebbe traccia di ogni passaggio attraverso eventuali +collegamenti simbolici. Per cambiare la directory di lavoro si può usare la funzione di sistema \funcd{chdir}, equivalente del comando di shell \cmd{cd}, il cui nome sta @@ -2720,11 +2751,11 @@ appunto per \textit{change directory}, il suo prototipo è: \begin{errlist} \item[\errcode{EACCES}] manca il permesso di ricerca su uno dei componenti di \param{pathname}. + \item[\errcode{ENAMETOOLONG}] il nome indicato in \param{path} è troppo lungo. \item[\errcode{ENOTDIR}] non si è specificata una directory. \end{errlist} - ed inoltre \errval{EFAULT}, \errval{EIO}, \errval{ELOOP}, - \errval{ENAMETOOLONG}, \errval{ENOENT} e \errval{ENOMEM} nel loro - significato generico.} + ed inoltre \errval{EFAULT}, \errval{EIO}, \errval{ELOOP}, \errval{ENOENT} e + \errval{ENOMEM} nel loro significato generico.} \end{funcproto} La funzione cambia la directory di lavoro in \param{pathname} ed @@ -2764,8 +2795,8 @@ ha il permesso di attraversamento alla directory specificata da \param{fd}. Finora abbiamo parlato esclusivamente di file, directory e collegamenti simbolici, ma in sez.~\ref{sec:file_file_types} abbiamo visto che il sistema prevede anche degli altri tipi di file, che in genere vanno sotto il nome -generico di \textsl{file speciali}, come i file di dispositivo, le \textit{fifo} ed i -socket. +generico di \textsl{file speciali}, come i file di dispositivo, le +\textit{fifo} ed i socket. La manipolazione delle caratteristiche di questi file speciali, il cambiamento di nome o la loro cancellazione può essere effettuata con le stesse funzioni @@ -2830,9 +2861,9 @@ dispositivo usando questa funzione (il processo deve avere la capacità la specifica \func{mkfifo}.} l'uso per la creazione di un file ordinario, di una \textit{fifo} o di un socket è consentito anche agli utenti normali. -I nuovi \textit{inode} creati con \func{mknod} apparterranno al proprietario e -al gruppo del processo (usando \ids{UID} e \ids{GID} del gruppo effettivo) che -li ha creati a meno non sia presente il bit \acr{sgid} per la directory o sia +Gli \textit{inode} creati con \func{mknod} apparterranno al proprietario e al +gruppo del processo (usando \ids{UID} e \ids{GID} del gruppo effettivo) che li +ha creati a meno non sia presente il bit \acr{sgid} per la directory o sia stata attivata la semantica BSD per il filesystem (si veda sez.~\ref{sec:file_ownership_management}) in cui si va a creare l'\textit{inode}, nel qual caso per il gruppo verrà usato il \ids{GID} del @@ -2958,7 +2989,10 @@ attaccante allora potrà sfruttarla con quello che viene chiamato ``\textit{symlink attack}'' dove nell'intervallo fra la generazione di un nome e l'accesso allo stesso, viene creato un collegamento simbolico con quel nome verso un file diverso, ottenendo, se il programma sotto attacco ne ha la -capacità, un accesso privilegiato. +capacità, un accesso privilegiato.\footnote{dal kernel 3.6 sono state + introdotte delle contromisure, illustrate in + sez.~\ref{sec:procadv_security_misc}, che rendono impraticabili questo tipo + di attacchi, ma questa non è una buona scusa per ignorare il problema.} \itindend{symlink~attack} @@ -3110,7 +3144,6 @@ prototipo è: \end{errlist}} \end{funcproto} - Come per \func{mktemp} anche in questo caso \param{template} non può essere una stringa costante. La funzione apre un file in lettura/scrittura con la funzione \func{open}, usando l'opzione \const{O\_EXCL} (si veda @@ -3136,14 +3169,40 @@ specificamente dalla \acr{glibc},\footnote{la funzione è stata introdotta \func{mkstemp}.} \end{funcproto} \noindent la cui sola differenza è la presenza dell'ulteriore argomento -\var{flags} che consente di specificare i flag da passare ad \func{open} -nell'apertura del file. +\var{flags} che consente di specificare alcuni ulteriori flag +(\const{O\_APPEND}, \const{O\_CLOEXEC}, \const{O\_SYNC}, il cui significato +vedremo in sez.~\ref{sec:file_open_close}) da passare ad \func{open} +nell'apertura del file. + +Di queste due funzioni sono state poi introdotte a partire dalla \acr{glibc} +2.11 due varianti, \funcd{mkstemps} e \funcd{mkostemps} che consentono di +indicare anche un suffisso, i loro prototipo sono: + +\begin{funcproto}{ +\fhead{stlib.h} +\fdecl{int mkstemps(char *template, int suffixlen)} +\fdesc{Apre un file temporaneo.} +\fdecl{int mkostemps(char *template, int suffixlen, int flags)} +\fdesc{Apre un file temporaneo.} +} + +{Le funzioni hanno gli stessi valori di ritorno e gli stessi errori di + \func{mkstemp} con lo stesso significato tranne \errval{EINVAL} che viene + restituito se \param{template} non è di lunghezza pari ad almeno + $6+$\param{suffixlen} ed i 6 caratteri prima del suffisso non sono + \code{XXXXXX}.} +\end{funcproto} +Le due funzioni, estensione non standard delle \acr{glibc}, sono identiche a +\funcd{mkstemp} e \funcd{mkostemp}, ma consentono di avere un nome del file +nella forma \texttt{prefissoXXXXXXsuffisso} dove la lunghezza del suffisso +deve essere indicata con \param{suffixlen}. -In OpenBSD è stata introdotta un'altra funzione simile alle precedenti, -\funcd{mkdtemp}, che crea invece una directory temporanea;\footnote{la - funzione è stata introdotta nella \acr{glibc} a partire dalla versione - 2.1.91 ed inserita nello standard POSIX.1-2008.} il suo prototipo è: +Infine con OpenBSD è stata introdotta un'altra funzione simile alle +precedenti, \funcd{mkdtemp}, che crea invece una directory +temporanea;\footnote{la funzione è stata introdotta nella \acr{glibc} a + partire dalla versione 2.1.91 ed inserita nello standard POSIX.1-2008.} il +suo prototipo è: \begin{funcproto}{ \fhead{stlib.h} @@ -3162,7 +3221,7 @@ In OpenBSD è stata introdotta un'altra funzione simile alle precedenti, La funzione crea una directory temporanea il cui nome è ottenuto sostituendo le \code{XXXXXX} finali di \param{template} con permessi \code{0700} (si veda sez.~\ref{sec:file_perm_overview} per i dettagli). Dato che la creazione della -directory è sempre esclusiva i precedenti problemi di \textit{race condition} +directory è sempre atomica i precedenti problemi di \textit{race condition} non si pongono. @@ -6661,9 +6720,10 @@ librerie) di cui il server potrebbe avere bisogno. % LocalWords: setmntent getmntent addmntent endmntent hasmntopt such offsetof % LocalWords: member scan attack EOVERFLOW BITS blkcnt rdev FDCWD functions % LocalWords: faccessat grpid lacl AppArmor capsetp mygetfacl table Tb MSK -% LocalWords: LAZYTIME submount peer +% LocalWords: LAZYTIME submount peer protected hardlink symlinks silly %%% Local Variables: %%% mode: latex %%% TeX-master: "gapil" %%% End: +% LocalWords: renames