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
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
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
\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}
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
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.}
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}{
\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,
{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
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
\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}
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}
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
\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
% 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