In questo capitolo tratteremo in dettaglio le modalità con cui si gestiscono
file e directory, iniziando dalle funzioni di libreria che si usano per
copiarli, spostarli e cambiarne i nomi. Esamineremo poi l'interfaccia che
-permette la manipolazione dei vari attributi di file e directory ed alla
-fine faremo una trattazione dettagliata su come è strutturato il sistema base
-di protezioni e controllo di accesso ai file e sulle funzioni che ne
-permettono la gestione. Tutto quello che riguarda invece la manipolazione del
-contenuto dei file è lasciato ai capitoli successivi.
+permette la manipolazione dei vari attributi di file e directory ed alla fine
+faremo una trattazione dettagliata su come è strutturato il sistema base di
+protezioni e controllo dell'accesso ai file e sulle funzioni che ne permettono
+la gestione. Tutto quello che riguarda invece la manipolazione del contenuto
+dei file è lasciato ai capitoli successivi.
funzioni usate per manipolazione nel filesytem di file e directory, per la
creazione di link simbolici e diretti, per la gestione e la lettura delle
directory; il tutto mettendo in evidenza le conseguenze della struttura
-standard della gestione dei file in un sistema unix-like, già accennate al
+standard della gestione dei file in un sistema unix-like, introdotta nel
capitolo precedente.
permettono di fare riferimento allo stesso file chiamandolo con nomi diversi
o accedendovi da directory diverse.
-Questo è possibile anche in ambiente unix, dove tali collegamenti sono
+Questo è possibile anche in ambiente Unix, dove tali collegamenti sono
usualmente chiamati \textit{link}; ma data la struttura del sistema di
gestione dei file (ed in particolare quanto trattato in
-\secref{sec:file_architecture}) ci sono due metodi sostanzialmente diversi per
+\secref{sec:file_arch_func}) ci sono due metodi sostanzialmente diversi per
fare questa operazione.
-Come spiegato in \secref{sec:file_filesystem} l'accesso al contenuto di
-un file su disco avviene attraverso il suo inode, e il nome che si trova in
-una directory è solo una etichetta associata ad un puntatore a che fa
+Come spiegato in \secref{sec:file_filesystem} l'accesso al contenuto di un
+file su disco avviene attraverso il suo inode\index{inode}, e il nome che si
+trova in una directory è solo una etichetta associata ad un puntatore a che fa
riferimento al suddetto inode.
Questo significa che la realizzazione di un link è immediata in quanto uno
stesso file può avere tanti nomi diversi allo stesso tempo, dati da
altrettante diverse associazioni allo stesso inode; si noti poi che nessuno di
-questi nomi viene ad assumere una particolare preferenza rispetto agli altri.
+questi nomi viene ad assumere una particolare preferenza o originalità
+rispetto agli altri.
Per aggiungere un nome ad un inode si utilizza la funzione \func{link}; si
suole chiamare questo tipo di associazione un collegamento diretto (o
Windows).
La funzione inoltre opera sia sui file ordinari che sugli altri oggetti del
-filesystem, con l'eccezione delle directory. In alcuni versioni di unix solo
+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
+directory: questo viene fatto perché con una tale operazione è possibile
creare dei circoli nel filesystem (vedi l'esempio mostrato in
\secref{sec:file_symlink}, dove riprenderemo il discorso) che molti programmi
non sono in grado di gestire e la cui rimozione diventerebbe estremamente
Una delle caratteristiche di queste funzioni è che la creazione/rimozione
della nome dalla directory e l'incremento/decremento del numero di riferimenti
-nell'inode deve essere una operazione atomica (si veda
-\secref{sec:proc_atom_oper}), per questo entrambe queste funzioni sono
-realizzate tramite una singola system call.
+nell'inode devono essere effettuati in maniera atomica (si veda
+\secref{sec:proc_atom_oper}) senza possibili interruzioni fra le due
+operazioni, per questo entrambe queste funzioni sono realizzate tramite una
+singola system call.
Si ricordi infine che il file non viene eliminato dal disco fintanto che tutti
i riferimenti ad esso sono stati cancellati, solo quando il \textit{link
\macro{EISDIR}). Nel caso \var{newpath} indichi un file esistente questo viene
cancellato e rimpiazzato (atomicamente).
-Se \var{oldpath} è una directory allora \var{newpath} se esiste deve essere
+Se \var{oldpath} è una directory allora \var{newpath}, se esiste, deve essere
una directory vuota, altrimenti si avranno gli errori \macro{ENOTDIR} (se non
è una directory) o \macro{ENOTEMPTY} (se non è vuota). Chiaramente
\var{newpath} non può contenere \var{oldpath} altrimenti si avrà un errore
\var{newpath} è un link simbolico verrà cancellato come qualunque altro file.
Infine qualora \var{oldpath} e \var{newpath} siano due nomi dello stesso file
lo standard POSIX prevede che la funzione non dia errore, e non faccia nulla,
-lasciando entrambi i nomi; Linux segue questo standard, anche se come fatto
-notare dal manuale delle glibc, il comportamento più ragionevole sarebbe
-quello di cancellare \var{oldpath}.
+lasciando entrambi i nomi; Linux segue questo standard, anche se, come fatto
+notare dal manuale delle \textit{glibc}, il comportamento più ragionevole
+sarebbe quello di cancellare \var{oldpath}.
Il vantaggio nell'uso di questa funzione al posto della chiamata successiva di
\func{link} e \func{unlink} è che l'operazione è eseguita atomicamente, non
In ogni caso se \var{newpath} esiste e l'operazione fallisce per un qualche
motivo (come un crash del kernel), \func{rename} garantisce di lasciare
-presente una istanza di \var{newpath}, tuttavia nella sovrascrittura potrà
+presente una istanza di \var{newpath}. Tuttavia nella sovrascrittura potrà
esistere una finestra in cui sia \var{oldpath} che \var{newpath} fanno
riferimento allo stesso file.
Come abbiamo visto in \secref{sec:file_link} la funzione \func{link} crea
riferimenti agli inodes, pertanto può funzionare soltanto per file che
-risiedono sullo stesso filesystem e solo per un filesystem di tipo unix.
+risiedono sullo stesso filesystem e solo per un filesystem di tipo Unix.
Inoltre abbiamo visto che in Linux non è consentito eseguire un link diretto
ad una directory.
-Per ovviare a queste limitazioni i sistemi unix supportano un'altra forma di
+Per ovviare a queste limitazioni i sistemi Unix supportano un'altra forma di
link (i cosiddetti \textit{soft link} o \textit{symbolic link}), che sono,
come avviene in altri sistemi operativi, dei file speciali che contengono il
semplicemente il riferimento ad un altro file (o directory). In questo modo è
-possibile effettuare link anche attraverso filesystem diversi, a file posti in
-filesystem che non supportano i link diretti, a delle directory, e anche a
+possibile effettuare link anche attraverso filesystem diversi, a file posti
+in filesystem che non supportano i link diretti, a delle directory, ed anche a
file che non esistono ancora.
Il sistema funziona in quanto i link simbolici sono contrassegnati come tali
\bodydesc{La funzione restituisce zero in caso di successo e -1 per un
errore, nel qual caso la variabile \var{errno} restituisce i valori:
\begin{errlist}
- \item[\macro{EPERM}] il filesystem che contiene \param{newpath} non supporta i
- link simbolici.
+ \item[\macro{EPERM}] il filesystem che contiene \param{newpath} non supporta
+ i link simbolici.
\item[\macro{ENOENT}] una componente di \param{newpath} non esiste o
\param{oldpath} è una stringa vuota.
\item[\macro{EEXIST}] esiste già un file \param{newpath}.
Si tenga presente che la funzione non effettua nessun controllo sull'esistenza
di un file di nome \param{oldpath}, ma si limita ad inserire quella stringa
nel link simbolico. Pertanto un link simbolico può anche riferirsi ad un file
-che non esiste: quello che viene chiamato un \textit{dangling link},
-letteralmente \textsl{link ciondolante}.
-
+che non esiste: in questo caso si ha quello che viene chiamato un
+\textit{dangling link}, letteralmente un \textsl{link ciondolante}.
Come accennato i link simbolici sono risolti automaticamente dal kernel
all'invocazione delle varie system call; in \ntab\ si è riportato un elenco
\var{buff} o -1 per un errore, nel qual caso la variabile
\var{errno} viene settata a:
\begin{errlist}
- \item[\macro{EINVAL}] \var{file} non è un link simbolico o \var{size} non è
- positiva.
- \item[\macro{EROFS}] La directory su cui si vuole inserire il nuovo link è
- su un filesystem montato in sola lettura.
- \item[\macro{ENOSPC}] La directory o il filesystem in cui si vuole creare il
- link è piena e non c'è ulteriore spazio disponibile.
+ \item[\macro{EINVAL}] \param{path} non è un link simbolico o \param{size}
+ non è positiva.
\end{errlist}
ed inoltre \macro{ENOTDIR}, \macro{ENAMETOOLONG}, \macro{ENOENT},
\macro{EACCES}, \macro{ELOOP}, \macro{EIO}, \macro{EFAULT} e
\begin{figure}[htb]
\centering
- \includegraphics[width=5cm]{img/link_loop}
+ \includegraphics[width=7cm]{img/link_loop}
\caption{Esempio di loop nel filesystem creato con un link simbolico.}
\label{fig:file_link_loop}
\end{figure}
la struttura della directory \file{/boot}. Come si vede si è creato al suo
interno un link simbolico che punta di nuovo a \file{/boot}\footnote{Questo
tipo di loop è stato effettuato per poter permettere a \cmd{grub} (un
- bootloader estremamente avanzato in grado di accedere direttamente
- attraverso vari filesystem al file da lanciare come sistema operativo) di
- vedere i file in questa directory, che è montata su una partizione separata
- (e che grub vedrebbe come radice), con lo stesso path con cui verrebbero
- visti dal sistema operativo.}.
+ bootloader in grado di leggere direttamente da vari filesystem il file da
+ lanciare come sistema operativo) di vedere i file in questa directory con lo
+ stesso path con cui verrebbero visti dal sistema operativo, anche se essi si
+ trovano, come è solito, su una partizione separata (e che \cmd{grub}
+ vedrebbe come radice).}.
Questo può causare problemi per tutti quei programmi che effettuano la
scansione di una directory senza tener conto dei link simbolici, ad esempio se
-lanciassimo un comando del tipo \cmd{grep -r linux *}, il loop nella directory
-porterebbe il comando ad esaminare \file{/boot}, \file{/boot/boot},
+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.
Per questo motivo il kernel e le librerie prevedono che nella risoluzione di
un pathname possano essere seguiti un numero limitato di link simbolici, il
-cui valore limite è specificato dalla costante \macro{MAXSYMLINKS}; qualora
+cui valore limite è specificato dalla costante \macro{MAXSYMLINKS}. Qualora
questo limite venga superato viene generato un errore ed \var{errno} viene
settata al valore \macro{ELOOP}.
-Un punto da tenere sempre presente è il fatto che un link simbolico può fare
-riferimento anche ad un file che non esiste; ad esempio possiamo creare un
-file temporaneo nella nostra directory con un link del tipo:
+Un punto da tenere sempre presente è che, come abbiamo accennato, un link
+simbolico può fare riferimento anche ad un file che non esiste; ad esempio
+possiamo creare un file temporaneo nella nostra directory con un link del
+tipo:
\begin{verbatim}
$ ln -s /tmp/tmp_file temporaneo
\end{verbatim}%$
$ cat temporaneo
cat: temporaneo: No such file or directory
\end{verbatim}%$
-con un errore che può sembrare sbagliato, dato che invece \cmd{ls} ci
-mostrerebbe l'esistenza di \file{temporaneo}.
+con un errore che può sembrare sbagliato, dato che una ispezione con \cmd{ls}
+ci mostrerebbe invece l'esistenza di \file{temporaneo}.
\subsection{La creazione e la cancellazione delle directory}
\macro{ENOENT}, \macro{ENOTDIR}, \macro{ENOMEM}, \macro{ELOOP},
\macro{EROFS}.}
\end{prototype}
-
+
La funzione crea una nuova directory vuota (che contiene solo le due voci
standard \file{.} e \file{..}). I permessi di accesso (vedi la trattazione in
\secref{sec:file_access_control}) specificati da \var{mode} (i cui possibili
degli altri tipi di file, come i file di dispositivo e le fifo (i socket sono
un caso a parte, che vedremo in \secref{cha:socket_intro}).
-La manipolazione delle caratteristiche di questi filee e la loro cancellazione
+La manipolazione delle caratteristiche di questi file e la loro cancellazione
può essere effettuata con le stesse funzioni che operano sui file normali; ma
quando li si devono creare sono necessarie delle funzioni apposite. La prima
di queste funzioni è \func{mknod}, il suo prototipo è:
La funzione permette di creare un file speciale, ma si può usare anche per
creare file normali e fifo; l'argomento \param{mode} specifica il tipo di file
che si vuole creare ed i relativi permessi, secondo i valori riportati in
-\tabref{tab:file_mode_flags}, che vanno combinato come OR binario. I permessi
-sono comunque modificati nella maniera usuale dal valore di \var{umask} (si
-veda \secref{sec:file_umask}.
+\tabref{tab:file_mode_flags}, che vanno combinati con un OR binario. I
+permessi sono comunque modificati nella maniera usuale dal valore di
+\var{umask} (si veda \secref{sec:file_umask}).
Per il tipo di file può essere specificato solo uno fra: \macro{S\_IFREG} per
un file normale (che sarà creato vuoto), \macro{S\_IFBLK} per un device a
agli utenti normali.
I nuovi inode creati con \func{mknod} apparterranno al proprietario e al
-gruppo del processo che li creati, a meno che non si sia attivato il bit
+gruppo del processo che li ha creati, a meno che non si sia attivato il bit
\acr{sgid} per la directory o sia stata attivata la semantica BSD per il
filesystem (si veda \secref{sec:file_ownership}) in cui si va a creare
l'inode.
\bodydesc{La funzione restituisce zero in caso di successo e -1 per un
errore, nel qual caso \var{errno} assumerà i valori \macro{EACCESS},
\macro{EEXIST}, \macro{ENAMETOOLONG}, \macro{ENOENT}, \macro{ENOSPC},
- \macro{ENOTDIR} e\macro{EROFS}.}
+ \macro{ENOTDIR} e \macro{EROFS}.}
\end{functions}
\noindent come per \func{mknod} il file \param{pathname} non deve esistere
(neanche come link simbolico); al solito i permessi specificati da
perderebbe traccia di ogni passaggio attraverso eventuali link simbolici.
Per cambiare la directory di lavoro corrente si può usare la funzione
-\func{chdir} (omonima dell'analogo comando di shell) il cui nome sta appunto
-per \textit{change directory}), il suo prototipo è:
+\func{chdir} (equivalente del comando di shell \cmd{cd}) il cui nome sta
+appunto per \textit{change directory}, il suo prototipo è:
\begin{prototype}{unistd.h}{int chdir(const char *pathname)}
Cambia la directory di lavoro corrente in \param{pathname}.
\subsection{I file temporanei}
\label{sec:file_temp_file}
-In molte occasioni è utile poter creare dei file temporanei; benchè la cosa
+In molte occasioni è utile poter creare dei file temporanei; benché la cosa
sembri semplice in realtà il problema è più sottile di quanto non appaia a
prima vista. Infatti anche se sembrerebbe banale generare un nome a caso e
creare il file dopo aver controllato che questo non esista, nel momento fra il
controllo e la creazione si ha giusto lo spazio per una \textit{race
condition} (si ricordi quanto visto in \secref{sec:proc_race_cond}).
-Per questo motivo il kernel le \acr{glibc} provvedono una serie di funzioni da
-utilizzare per la gestione dei file temporanei.
+Le \acr{glibc} provvedono varie funzioni per generare nomi di file temporanei,
+di cui si abbia certezza di unicità (al momento della generazione); la prima
+di queste funzioni è \func{tmpnam} il cui prototipo è:
+\begin{prototype}{stdio.h}{char *tmpnam(char *string)}
+ Restituisce il puntatore ad una stringa contente un nome di file valido e
+ non esistente al momento dell'invocazione.
+ \bodydesc{La funzione ritorna il puntatore alla stringa con il nome o
+ \macro{NULL} in caso di fallimento. Non sono definiti errori.}
+\end{prototype}
+\noindent se si è passato un puntatore \param{string} non nullo questo deve
+essere di dimensione \macro{L\_tmpnam} (costante definita in \file{stdio.h},
+come \macro{P\_tmpdir} e \macro{TMP\_MAX}) ed il nome generato vi verrà
+copiato automaticamente; altrimenti il nome sarà generato in un buffer statico
+interno che verrà sovrascritto ad una chiamata successiva. Successive
+invocazioni della funzione continueranno a restituire nomi unici fino ad un
+massimo di \macro{TMP\_MAX} volte. Al nome viene automaticamente aggiunto come
+prefisso la directory specificata da \macro{P\_tmpdir}.
+
+Di questa funzione esiste una versione rientrante, \func{tmpnam\_r}, che non
+fa nulla quando si passa \macro{NULL} come parametro. Una funzione simile,
+\func{tempnam}, permette di specificare un prefisso per il file
+esplicitamente, il suo prototipo è:
+\begin{prototype}{stdio.h}{char *tempnam(const char *dir, const char *pfx)}
+ Restituisce il puntatore ad una stringa contente un nome di file valido e
+ non esistente al momento dell'invocazione.
+
+ \bodydesc{La funzione ritorna il puntatore alla stringa con il nome o
+ \macro{NULL} in caso di fallimento, \var{errno} viene settata a
+ \macro{ENOMEM} qualora fallisca l'allocazione della stringa.}
+\end{prototype}
+
+La funzione alloca con \code{malloc} la stringa in cui restituisce il nome,
+per cui è sempre rientrante, occorre però ricordarsi di disallocare il
+puntatore che restituisce. L'argomento \param{pfx} specifica un prefisso di
+massimo 5 caratteri per il nome provvisorio. La funzione assegna come
+directory per il file temporaneo (verificando che esista e sia accessibili),
+la prima valida delle seguenti:
+\begin{itemize*}
+\item La variabile di ambiente \macro{TMPNAME} (non ha effetto se non è
+ definita o se il programma chiamante è \acr{suid} o \acr{sgid}, vedi
+ \secref{sec:file_suid_sgid}).
+\item il valore dell'argomento \param{dir} (se diverso da \macro{NULL}).
+\item Il valore della costante \macro{P\_tmpdir}.
+\item la directory \file{/tmp}.
+\end{itemize*}
+
+In ogni caso, anche se la generazione del nome è casuale, ed è molto difficile
+ottere un nome duplicato, nulla assicura che un altro processo non possa avere
+creato, fra l'ottenimento del nome e l'apertura del file, un altro file con lo
+stesso nome; per questo motivo quando si usa il nome ottenuto da una di queste
+funzioni occorre sempre aprire il nuovo file in modalità di esclusione (cioè
+con l'opzione \macro{O\_EXCL} per i file descriptor o con il flag \code{x} per
+gli stream) che fa fallire l'apertura in caso il file sia già esistente.
+
+Per evitare di dovere effettuare a mano tutti questi controlli, lo standard
+POSIX definisce la funzione \func{tempfile}, il cui prototipo è:
+\begin{prototype}{stdio.h}{FILE *tmpfile (void)}
+ Restituisce un file temporaneo aperto in lettura/scrittura.
+
+ \bodydesc{La funzione ritorna il puntatore allo stream associato al file
+ temporaneo in caso di successo e \macro{NULL} in caso di errore, nel qual
+ caso \var{errno} viene settata a
+ \begin{errlist}
+ \item[\macro{EINTR}] La funzione è stata interrotta da un segnale.
+ \item[\macro{EEXIST}] Non è stato possibile generare un nome univoco.
+ \end{errlist}
+ ed inoltre \macro{EFAULT}, \macro{EMFILE}, \macro{ENFILE}, \macro{ENOSPC},
+ \macro{EROFS} e \macro{EACCESS}.}
+\end{prototype}
+\noindent essa restituisce direttamente uno stream già aperto (in modalità
+\code{r+b}, si veda \secref{sec:file_fopen}) e pronto per l'uso, che viene
+automaticamente cancellato alla sua chiusura o all'uscita dal programma. Lo
+standard non specifica in quale directory verrà aperto il file, ma \acr{glibc}
+prima tentano con \macro{P\_tmpdir} e poi con \file{/tmp}. Questa funzione è
+rientrante e non soffre di problemi di \textit{race condition}.
+
+Alcune versioni meno recenti di Unix non supportano queste funzioni; in questo
+caso si possono usare le vecchie funzioni \func{mktemp} e \func{mkstemp} che
+modificano una stringa di input che serve da modello e che deve essere
+conclusa da 6 caratteri \code{X} che verranno sostituiti da un codice
+unico. La prima delle due è analoga a \func{tmpnam} e genera un nome casuale,
+il suo prototipo è:
+\begin{prototype}{stlib.h}{char *mktemp(char *template)}
+ Genera un filename univoco sostituendo le \code{XXXXXX} finali di
+ \param{template}.
+
+ \bodydesc{La funzione ritorna il puntatore \param{template} in caso di
+ successo e \macro{NULL} in caso di errore, nel qual caso \var{errno} viene
+ settata a:
+ \begin{errlist}
+ \item[\macro{EINVAL}] \param{template} non termina con \code{XXXXXX}.
+ \end{errlist}}
+\end{prototype}
+\noindent dato che \param{template} deve poter essere modificata dalla
+funzione non si può usare una stringa costante. Tutte le avvertenze riguardo
+alle possibili \textit{race condition} date per \func{tmpnam} continuano a
+valere; inoltre in alcune vecchie implementazioni il valore di usato per
+sostituire le \code{XXXXXX} viene formato con il \acr{pid} del processo più
+una lettera, il che mette a disposizione solo 26 possibilità diverse per il
+nome del file, e rende il nome temporaneo facile da indovinare. Per tutti
+questi motivi la funzione è deprecata e non dovrebbe mai essere usata.
+
+
+
+La seconda funzione, \func{mkstemp} è sostanzialmente equivalente a
+\func{tmpfile}, ma restituisce un file descriptor invece di uno stream; il suo
+prototipo è:
+\begin{prototype}{stlib.h}{int mkstemp(char *template)}
+ Genera un file temporaneo con un nome ottenuto sostituendo le \code{XXXXXX}
+ finali di \param{template}.
+
+ \bodydesc{La funzione ritorna il file descriptor in caso successo e
+ -1 in caso di errore, nel qual caso \var{errno} viene settata a:
+ \begin{errlist}
+ \item[\macro{EINVAL}] \param{template} non termina con \code{XXXXXX}.
+ \item[\macro{EEXIST}] non è riuscita a creare un file temporano, il
+ contenuto di \param{template} è indefinito.
+ \end{errlist}}
+\end{prototype}
+\noindent 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 \macro{O\_EXCL} (si veda
+\secref{sec:file_open}), in questo modo al ritorno della funzione si ha la
+certezza di essere i soli utenti del file. I permessi sono settati al valore
+\code{0600}\footnote{questo è vero a partire dalle \acr{glibc} 2.0.7, le
+ versioni precedenti delle \acr{glibc} e le vecchie \acr{libc5} e \acr{libc4}
+ usavano il valore \code{0666} che permetteva a chiunque di leggere i
+ contenuti del file.} (si veda \secref{sec:file_perm_overview}).
+
+In OpenBSD è stata introdotta un'altra funzione\footnote{introdotta anche in
+ Linux a partire dalle \acr{glibc} 2.1.91.} simile alle precedenti,
+\func{mkdtemp}, che crea una directory temporanea; il suo prototipo è:
+\begin{prototype}{stlib.h}{char *mkdtemp(char *template)}
+ Genera una directory temporaneo il cui nome è ottenuto sostituendo le
+ \code{XXXXXX} finali di \param{template}.
+
+ \bodydesc{La funzione ritorna il puntatore al nome della directory in caso
+ successo e \macro{NULL} in caso di errore, nel qual caso \var{errno} viene
+ settata a:
+ \begin{errlist}
+ \item[\macro{EINVAL}] \param{template} non termina con \code{XXXXXX}.
+ \end{errlist}
+ più gli altri eventuali codici di errore di \func{mkdir}.}
+\end{prototype}
+\noindent la directory è creata con permessi \code{0700} (al solito si veda
+\capref{cha:file_unix_interface} per i dettagli); dato che la creazione della
+directory è sempre esclusiva i precedenti problemi di \textit{race condition}
+non si pongono.
\section{La manipolazione delle caratteristiche dei files}
\macro{ELOOP}, \macro{EFAULT}, \macro{EACCESS}, \macro{ENOMEM},
\macro{ENAMETOOLONG}.}
\end{functions}
+\noindent il loro comportamento è identico, solo che operano rispettivamente
+su un file, su un link simbolico e su un file descriptor.
-La struttura \var{stat} è definita nell'header \file{sys/stat.h} e in
-generale dipende dall'implementazione, la versione usata da Linux è mostrata
-in \nfig, così come riportata dalla man page (in realtà la definizione
-effettivamente usata nel kernel dipende dall'architettura e ha altri campi
-riservati per estensioni come tempi più precisi, o per il padding dei campi).
+La struttura \var{stat} usata da queste funzioni è definita nell'header
+\file{sys/stat.h} e in generale dipende dall'implementazione, la versione
+usata da Linux è mostrata in \nfig, così come riportata dalla man page di
+\func{stat} (in realtà la definizione effettivamente usata nel kernel dipende
+dall'architettura e ha altri campi riservati per estensioni come tempi più
+precisi, o per il padding dei campi).
\begin{figure}[!htb]
\footnotesize
\subsection{I tipi di file}
\label{sec:file_types}
-Come riportato in \tabref{tab:file_file_types} in Linux oltre ai file e
-alle directory esistono vari altri oggetti che possono stare su un filesystem;
-il tipo di file è ritornato dalla \func{stat} nel campo \var{st\_mode}
-(che è quello che contiene anche le informazioni relative ai permessi).
+Come riportato in \tabref{tab:file_file_types} in Linux oltre ai file e alle
+directory esistono vari altri oggetti che possono stare su un filesystem. Il
+tipo di file è ritornato dalla \func{stat} come maschera binaria nel campo
+\var{st\_mode} (che che contiene anche le informazioni relative ai permessi).
Dato che il valore numerico può variare a seconda delle implementazioni, lo
standard POSIX definisce un insieme di macro per verificare il tipo di files,
-queste vengono usate anche da Linux che supporta pure le estensioni per link
-simbolici e socket definite da BSD, l'elenco completo di tutte le macro è
+queste vengono usate anche da Linux che supporta pure le estensioni allo
+standard per i link simbolici e i socket definite da BSD; l'elenco completo
+delle macro con cui è possibile estrarre l'informazione da \var{st\_mode} è
riportato in \ntab.
\begin{table}[htb]
\centering
\label{tab:file_type_macro}
\end{table}
-Oltre a queste macro è possibile usare direttamente il valore di
-\var{st\_mode} per ricavare il significato dei vari bit in esso memorizzati,
-per questo sempre in \file{sys/stat.h} sono definiti i flag riportati in
-\ntab:
+Oltre alle macro di \tabref{tab:file_type_macro} è possibile usare
+direttamente il valore di \var{st\_mode} per ricavare il tipo di file
+controllando direttamente i vari bit in esso memorizzati. Per questo sempre in
+\file{sys/stat.h} sono definite le costanti numeriche riportate in \ntab.
+
+Il primo valore dell'elenco di \secref{tab:file_mode_flags} è la maschera
+binaria che permette di estrarre i bit nei quali viene memorizzato il tipo di
+file, i valori successivi sono le costanti corrispondenti ai singoli bit, e
+possono essere usati per effettuare la selezione sul tipo di file voluto, con
+una opportuna combinazione.
+
\begin{table}[htb]
\centering
\footnotesize
\label{tab:file_mode_flags}
\end{table}
-Il primo valore definisce la maschera dei bit usati nei quali viene
-memorizzato il tipo di files, mentre gli altri possono essere usati per
-effettuare delle selezioni sul tipo di file voluto, combinando opportunamente
-i vari flag; ad esempio se si volesse controllare se un file è una directory o
-un file ordinario si potrebbe definire la condizione:
+Ad esempio se si volesse impostare una condizione che permetta di controllare
+se un file è una directory o un file ordinario si potrebbe definire la macro
+di preprocessore:
\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
#define IS_FILE_DIR(x) (((x) & S_IFMT) & (S_IFDIR | S_IFREG))
\end{lstlisting}
poi si effettua il confronto con la combinazione di tipi scelta.
-\subsection{La dimensione dei file}
+\subsection{Le dimensioni dei file}
\label{sec:file_file_size}
-Il membro \var{st\_size} contiene la dimensione del file in byte (se il file
-è un file normale, nel caso di un link simbolico al dimensione è quella del
-pathname che contiene).
+Il membro \var{st\_size} contiene la dimensione del file in byte (se il file è
+un file normale, nel caso di un link simbolico la dimensione è quella del
+pathname che contiene).
Il campo \var{st\_blocks} definisce la lunghezza del file in blocchi di 512
byte. Il campo \var{st\_blksize} infine definisce la dimensione preferita per
Si tenga conto che lunghezza del file riportata in \var{st\_size} non è detto
che corrisponda all'occupazione dello spazio su disco per via della possibile
-esistenza dei cosiddetti \textsl{buchi} (detti normalmente \textit{holes}) che
+esistenza dei cosiddetti \textit{holes} (letteralmente \textsl{buchi}) che
si formano tutte le volte che si va a scrivere su un file dopo aver eseguito
una \func{lseek} (vedi \secref{sec:file_lseek}) oltre la sua conclusione
corrente.
-In tal caso si avranno differenti risultati a seconda del modi in cui si
+In questo caso si avranno risultati differenti a seconda del modo in cui si
calcola la lunghezza del file, ad esempio il comando \cmd{du}, (che riporta il
numero di blocchi occupati) potrà dare una dimensione inferiore, mentre se si
legge dal file (ad esempio usando il comando \cmd{wc -c}), dato che in tal
Un file può sempre essere troncato a zero aprendolo con il flag
\macro{O\_TRUNC}, ma questo è un caso particolare; per qualunque altra
-dimensione si possono usare le due funzioni:
+dimensione si possono usare le due funzioni \func{truncate} e
+\func{ftruncate}, i cui prototipi sono:
\begin{functions}
\headdecl{unistd.h} \funcdecl{int truncate(const char *file\_name, off\_t
length)} Fa si che la dimensione del file \var{file\_name} sia troncata ad
\begin{tabular}[c]{|c|l|l|c|}
\hline
\textbf{Membro} & \textbf{Significato} & \textbf{Funzione}
- & \textbf{Opzione} \\
+ & \textbf{Opzione di \cmd{ls}} \\
\hline
\hline
\var{st\_atime}& ultimo accesso ai dati del file &\func{read},
\begin{tabular}[c]{|l|c|c|c|c|c|c|l|}
\hline
\multicolumn{1}{|p{3cm}|}{\centering{\vspace{6pt}\textbf{Funzione}}} &
- \multicolumn{3}{|p{3cm}|}{\centering{File o directory di riferimento}}&
- \multicolumn{3}{|p{3cm}|}{\centering{Directory genitrice del riferimento}}
+ \multicolumn{3}{|p{3.6cm}|}{\centering{
+ \textbf{File o directory del riferimento}}}&
+ \multicolumn{3}{|p{3.6cm}|}{\centering{
+ \textbf{Directory contenente il riferimento}}}
&\multicolumn{1}{|p{3.6cm}|}{\centering{\vspace{6pt}\textbf{Note}}} \\
\cline{2-7}
\cline{2-7}
\multicolumn{1}{|p{3cm}|}{}
- &\multicolumn{1}{|p{.8cm}|}{\centering{\textsl{(a)}}}
- &\multicolumn{1}{|p{.8cm}|}{\centering{\textsl{(m)}}}
- &\multicolumn{1}{|p{.8cm}|}{\centering{\textsl{(c)}}}
- &\multicolumn{1}{|p{.8cm}|}{\centering{\textsl{(a)}}}
- &\multicolumn{1}{|p{.8cm}|}{\centering{\textsl{(m)}}}
- &\multicolumn{1}{|p{.8cm}|}{\centering{\textsl{(c)}}}
+ &\multicolumn{1}{|p{.9cm}|}{\centering{\textsl{(a)}}}
+ &\multicolumn{1}{|p{.9cm}|}{\centering{\textsl{(m)}}}
+ &\multicolumn{1}{|p{.9cm}|}{\centering{\textsl{(c)}}}
+ &\multicolumn{1}{|p{.9cm}|}{\centering{\textsl{(a)}}}
+ &\multicolumn{1}{|p{.9cm}|}{\centering{\textsl{(m)}}}
+ &\multicolumn{1}{|p{.9cm}|}{\centering{\textsl{(c)}}}
&\multicolumn{1}{|p{3cm}|}{} \\
\hline
\hline
\func{read}
&$\bullet$& & & & & & \\
\func{remove}
- & & &$\bullet$& &$\bullet$&$\bullet$& using
+ & & &$\bullet$& &$\bullet$&$\bullet$& se esegue
\func{unlink}\\ \func{remove}
- & & & & &$\bullet$&$\bullet$& using
+ & & & & &$\bullet$&$\bullet$& se esegue
\func{rmdir}\\ \func{rename}
& & &$\bullet$& &$\bullet$&$\bullet$& per entrambi
gli argomenti\\ \func{rmdir}
\end{table}
Si noti infine come \var{st\_ctime} non abbia nulla a che fare con il tempo di
-creazione del file, usato in molti altri sistemi operativi, ma che in unix non
+creazione del file, usato in molti altri sistemi operativi, ma che in Unix non
esiste. Per questo motivo quando si copia un file, a meno di preservare
esplicitamente i tempi (ad esempio con l'opzione \cmd{-p} di \cmd{cp}) esso
avrà sempre il tempo corrente come data di ultima modifica.
\subsection{I permessi per l'accesso ai file}
\label{sec:file_perm_overview}
-Il controllo di accesso ai file in unix segue un modello abbastanza semplice
+Il controllo di accesso ai file in Unix segue un modello abbastanza semplice
(ma adatto alla gran parte delle esigenze) in cui si dividono i permessi su
tre livelli. Si tenga conto poi che quanto diremo è vero solo per filesystem
-di tipo unix, e non è detto che sia applicabile a un filesystem
+di tipo Unix, e non è detto che sia applicabile a un filesystem
qualunque\footnote{ed infatti non è vero per il filesystem vfat di Windows,
per il quale i permessi vengono assegnati in maniera fissa con un opzione in
- fase di montaggio}. Esistono inoltre estensioni che permettono di
+ fase di montaggio.}. Esistono inoltre estensioni che permettono di
implementare le ACL (\textit{Access Control List}) che sono un meccanismo di
controllo di accesso molto più sofisticato.
-Ad ogni file unix associa sempre l'utente che ne è proprietario (il cosiddetto
-\textit{owner}) e il gruppo di appartenenza, secondo il meccanismo degli
-identificatori di utenti e gruppi (\acr{uid} e \acr{gid}). Questi valori
+Ad ogni file Linux associa sempre l'utente che ne è proprietario (il
+cosiddetto \textit{owner}) e il gruppo di appartenenza, secondo il meccanismo
+degli identificatori di utenti e gruppi (\acr{uid} e \acr{gid}). Questi valori
sono accessibili da programma tramite i campi \var{st\_uid} e \var{st\_gid}
della struttura \var{stat} (si veda \secref{sec:file_stat}). Ad ogni file
-viene inoltre associato un insieme di permessi che sono divisi in tre classi,
+viene inoltre associato un insieme di permessi che sono divisi in tre livelli,
e cioè attribuiti rispettivamente all'utente proprietario del file, a un
qualunque utente faccia parte del gruppo cui appartiene il file, e a tutti gli
altri utenti.
I permessi, così come vengono presi dai comandi e dalle routine di sistema,
-sono espressi da un numero di 12 bit; di questi i nove meno significativi sono
+sono espressi da un numero a 12 bit; di questi i nove meno significativi sono
usati a gruppi di tre per indicare i permessi base di lettura, scrittura ed
esecuzione (indicati nei comandi di sistema con le lettere \cmd{w}, \cmd{r} e
\cmd{x}) ed applicabili rispettivamente al proprietario, al gruppo, a tutti
-gli altri. I restanti tre bit (\acr{suid}, \acr{sgid}, e
-\textsl{sticky}) sono usati per indicare alcune caratteristiche più complesse
-su cui torneremo in seguito (vedi \secref{sec:file_suid_sgid} e
-\secref{sec:file_sticky}).
-
-Anche i permessi, come tutte le altre informazioni generali, sono tenuti per
-ciascun file nell'inode; in particolare essi sono contenuti in alcuni bit
-del campo \var{st\_mode} della struttura letta da \func{stat} (di nuovo si veda
-\secref{sec:file_stat} per i dettagli).
-
-In genere ci si riferisce a questo raggruppamento dei permessi usando le
-lettere \cmd{u} (per \textit{user}), \cmd{g} (per \textit{group}) e \cmd{o}
-(per \textit{other}), inoltre se si vuole indicare tutti i raggruppamenti
-insieme si usa la lettera \cmd{a} (per \textit{all}). Si tenga ben presente
-questa distinzione dato che in certi casi, mutuando la terminologia in uso nel
-VMS, si parla dei permessi base come di permessi per \textit{owner},
-\textit{group} ed \textit{all}, le cui iniziali possono dar luogo a confusione.
-Le costanti che permettono di accedere al valore numerico di questi bit nel
-campo \var{st\_mode} sono riportate in \ntab.
+gli altri. I restanti tre bit (\acr{suid}, \acr{sgid}, e \textsl{sticky})
+sono usati per indicare alcune caratteristiche più complesse del meccanismo
+del controllo di accesso su cui torneremo in seguito (in
+\secref{sec:file_suid_sgid} e \secref{sec:file_sticky}).
+
+Anche i permessi, come tutte le altre informazioni pertinenti al file, sono
+memorizzati nell'inode; in particolare essi sono contenuti in alcuni bit del
+campo \var{st\_mode} della struttura \func{stat} (si veda
+\figref{fig:file_stat_struct}).
+
+In genere ci si riferisce ai tre livelli dei permessi usando le lettere
+\cmd{u} (per \textit{user}), \cmd{g} (per \textit{group}) e \cmd{o} (per
+\textit{other}), inoltre se si vuole indicare tutti i raggruppamenti insieme
+si usa la lettera \cmd{a} (per \textit{all}). Si tenga ben presente questa
+distinzione dato che in certi casi, mutuando la terminologia in uso nel VMS,
+si parla dei permessi base come di permessi per \textit{owner}, \textit{group}
+ed \textit{all}, le cui iniziali possono dar luogo a confusione. Le costanti
+che permettono di accedere al valore numerico di questi bit nel campo
+\var{st\_mode} sono riportate in \ntab.
\begin{table}[htb]
\centering
specificati dalle variabili \var{owner} e \var{group}.
\bodydesc{Le funzioni restituiscono zero in caso di successo e -1 per
- un errore, in caso di errore \texttt{errno} viene settato ai valori:
+ un errore, in caso di errore \var{errno} viene settato ai valori:
\begin{errlist}
\item[\macro{EPERM}] L'\textit{effective user id} non corrisponde a quello
del proprietario del file o non è zero, o utente e gruppo non sono validi
\label{sec:file_chroot}
Benché non abbia niente a che fare con permessi, utenti e gruppi, questa
-funzione viene usata spesso per limitare le capacità dei programmi, ed è
-pertanto pertinente al controllo di accesso. Come accennato in
-\secref{sec:proc_fork} ogni processo oltre ad una directory di lavoro
-corrente, ha anche una directory radice, cioè una directory che per il
-processo costituisce la radice dell'albero del filesystem.
-
-In generale questa directory coincide con la
-
+funzione viene usata spesso per restringere le capacità di acccesso di un
+programma ad una sezione limitata del filesystem, per cui ne parleremo in
+questa sezione.
+
+Come accennato in \secref{sec:proc_fork} ogni processo oltre ad una directory
+di lavoro corrente, ha anche una directory radice, che è la directory che per
+il processo costituisce la radice dell'albero dei file e rispetto alla quale
+vengono risolti i pathname assoluti (si ricordi quanto detto in
+\secref{sec:file_organization}).
+
+La radice viene eredidata dal padre per ogni processo figlio; come si può
+vedere da \figref{fig:proc_task_struct} è tenuta nella struttura
+\type{fs\_struct} insieme alla directory di lavoro corrente e alla
+\var{umask}, e quindi di norma coincide con la \file{/} del sistema.
+
+In certe situazioni però per motivi di sicurezza non si vuole che un processo
+possa accedere a tutto il filesystem; per questo si può cambiare la directory
+radice con la funzione \func{chroot}, il cui prototipo è:
+\begin{prototype}{unistd.h}{int chroot(const char *path)}
+ Cambia la directory radice del processo a quella specificata da
+ \param{path}.
+
+\bodydesc{La funzione restituisce zero in caso di successo e -1 per
+ un errore, in caso di errore \var{errno} viene settato ai valori:
+ \begin{errlist}
+ \item[\macro{EPERM}] L'\textit{effective user id} non è zero.
+ \end{errlist}
+ ed inoltre \macro{EFAULT}, \macro{ENAMETOOLONG}, \macro{ENOENT},
+ \macro{ENOMEM}, \macro{ENOTDIR}, \macro{EACCES}, \macro{ELOOP};
+ \macro{EROFS} e \macro{EIO}.}
+\end{prototype}
+\noindent in questo modo la directory radice del processo diventerà
+\param{path} (che ovviamente deve esistere) ed ogni pathname assoluto sarà
+risolto a partire da essa, rendendo impossibile accedere alla parte di albero
+sovrastante; si ha cioè quella che viene chiamata una \textit{chroot jail}.
+
+Solo l'amministratore può usare questa funzione, e la nuova radice, per quanto
+detto in \secref{sec:proc_fork}, sarà ereditata da tutti i processi figli. Si
+tenga presente che la funzione non cambia la directory di lavoro corrente, che
+potrebbe restare fuori dalla \textit{chroot jail}.
+
+Un caso tipico di uso di \func{chroot} è quello di un server ftp, in questo
+caso infatti si vuole che il server veda solo i file che deve trasferire, per
+cui in genere si esegue una \func{chroot} sulla directory che contiene i file.
+Si tenga presente però che in questo caso occorrerà replicare all'interno
+della \textit{chroot jail} tutti i file (in genere programmi e librerie) di
+cui il server potrebbe avere bisogno.
+
+
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: "gapil"
+%%% End: