Come già accennato in \secref{sec:file_filesystem} in un sistema unix-like la
gestione dei file ha delle caratteristiche specifiche che derivano
-direttamente dall'architettura del sistema; in questa sezione esamineremo le
-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, introdotta nel
-capitolo precedente.
+direttamente dall'architettura del sistema.
+
+In questa sezione esamineremo le funzioni usate per la manipolazione di file e
+directory, per la creazione di link simbolici e diretti, per la gestione e la
+lettura delle directory.
+
+In particolare ci soffermeremo sulle conseguenze che derivano
+dall'architettura dei filesystem illustrata nel capitolo precedente per quanto
+riguarda il comportamento delle varie funzioni.
\subsection{Le funzioni \func{link} e \func{unlink}}
\label{sec:file_link}
Una caratteristica comune a diversi sistemi operativi è quella di poter creare
-dei nomi fittizi (come gli alias del MacOS o i collegamenti di Windows) che
-permettono di fare riferimento allo stesso file chiamandolo con nomi diversi
-o accedendovi da directory diverse.
+dei nomi fittizi (come gli alias del MacOS o i collegamenti di Windows o i
+nomi logici del VMS) che 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
-usualmente chiamati \textit{link}; ma data la struttura del sistema di
-gestione dei file (ed in particolare quanto trattato in
+usualmente chiamati \textit{link}; ma data l'architettura del sistema riguardo
+la gestione dei file (ed in particolare quanto trattato in
\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\index{inode}, e il nome che si
-trova in una directory è solo un'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\index{inode}; si noti poi
-che nessuno di questi nomi viene ad assumere una particolare preferenza o
-originalità rispetto agli altri.
-
-Per aggiungere un nome ad un inode\index{inode} si utilizza la funzione
-\func{link}; si suole chiamare questo tipo di associazione un collegamento
-diretto (o \textit{hard link}). Il prototipo della funzione e le sue
-caratteristiche principali, come risultano dalla pagina di manuale, sono le
-seguenti:
+file su disco avviene passando attraverso il suo inode\index{inode}, che è la
+struttura usata dal kernel che lo identifica univocamente all'interno di un
+singolo filesystem. Il nome del file che si trova nella voce di una directory
+è solo un'etichetta che viene associata ad un puntatore che fa riferimento al
+suddetto inode.
+
+Questo significa che, fintanto che si resta sullo stesso filesystem, la
+realizzazione di un link è immediata, ed uno stesso file può avere tanti nomi
+diversi allo stesso tempo, dati da altrettante diverse associazioni allo
+stesso inode\index{inode}. Si noti anche che nessuno di questi nomi viene ad
+assumere una particolare preferenza o originalità rispetto agli altri.
+
+Per aggiungere ad una directory una voce che faccia riferimento ad un
+inode\index{inode} già esistente si utilizza la funzione \func{link}; si suole
+chiamare questo tipo di associazione un collegamento diretto (o \textit{hard
+ link}).
+
+Il prototipo della funzione e le sue caratteristiche principali,
+come risultano dalla pagina di manuale, sono le seguenti:
\begin{prototype}{unistd.h}
{int link(const char *oldpath, const char *newpath)}
- Crea un nuovo collegamento diretto al file indicato da \var{oldpath}
- dandogli nome \var{newpath}.
+ Crea un nuovo collegamento diretto al file indicato da \param{oldpath}
+ dandogli nome \param{newpath}.
- \bodydesc{La funzione restituisce zero in caso di successo e -1 in
- caso di errore. La variabile \var{errno} viene impostata
- opportunamente, i principali codici di errore sono:
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore nel qual caso \var{errno} viene impostata ai valori:
\begin{errlist}
\item[\errcode{EXDEV}] \param{oldpath} e \param{newpath} non sono sullo
stesso filesystem.
\end{prototype}
La creazione di un nuovo collegamento diretto non copia il contenuto del file,
-ma si limita a creare una voce nella directory specificata con \var{newpath} e
-ad aumentare di uno il numero di riferimenti al file (riportato nel campo
-\var{st\_nlink} della struttura \var{stat}, vedi \secref{sec:file_stat})
+ma si limita a creare una voce nella directory specificata con \param{newpath}
+e ad aumentare di uno il numero di riferimenti al file (riportato nel campo
+\var{st\_nlink} della struttura \struct{stat}, vedi \secref{sec:file_stat})
aggiungendo il nuovo nome ai precedenti. Si noti che uno stesso file può
essere così chiamato con vari nomi in diverse directory.
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 circoli nel filesystem (vedi l'esempio mostrato in
+creare dei \textit{loop} 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
complicata (in genere per questo tipo di errori occorre far girare il
all'interno di una directory) si effettua con la funzione \func{unlink}; il
suo prototipo è il seguente:
\begin{prototype}{unistd.h}{int unlink(const char *pathname)}
- Cancella il nome specificato dal pathname nella relativa directory e
- decrementa il numero di riferimenti nel relativo inode\index{inode}. Nel
- caso di link simbolico cancella il link simbolico; nel caso di
- socket\index{socket}, fifo o file di dispositivo\index{file!di dispositivo}
- rimuove il nome, ma come per i file i processi che hanno aperto uno di
- questi oggetti possono continuare ad utilizzarlo.
+
+ Cancella un file.
\bodydesc{La funzione restituisce zero in caso di successo e -1 per un
errore, nel qual caso il file non viene toccato. La variabile
\var{errno} viene impostata secondo i seguenti codici di errore:
\begin{errlist}
- \item[\errcode{EISDIR}] \var{pathname} si riferisce ad una directory
- (valore specifico ritornato da Linux che non consente l'uso di
- \var{unlink} con le directory, e non conforme allo standard POSIX, che
- prescrive invece l'uso di \errcode{EPERM} in caso l'operazione non sia
- consentita o il processo non abbia privilegi sufficienti).
- \item[\errcode{EROFS}] \var{pathname} è su un filesystem montato in sola
+ \item[\errcode{EISDIR}] \param{pathname} si riferisce ad una directory.
+ \footnotemark
+ \item[\errcode{EROFS}] \param{pathname} è su un filesystem montato in sola
lettura.
- \item[\errcode{EISDIR}] \var{pathname} fa riferimento a una directory.
+ \item[\errcode{EISDIR}] \param{pathname} fa riferimento a una directory.
\end{errlist}
ed inoltre: \errval{EACCES}, \errval{EFAULT}, \errval{ENOENT},
\errval{ENOTDIR}, \errval{ENOMEM}, \errval{EROFS}, \errval{ELOOP},
\errval{EIO}.}
\end{prototype}
+\footnotetext{questo è un valore specifico ritornato da Linux che non consente
+ l'uso di \func{unlink} con le directory (vedi \secref{sec:file_remove}). Non
+ è conforme allo standard POSIX, che prescrive invece l'uso di
+ \errcode{EPERM} in caso l'operazione non sia consentita o il processo non
+ abbia privilegi sufficienti.}
+
+La funzione cancella il nome specificato dal pathname nella relativa directory
+e decrementa il numero di riferimenti nel relativo inode\index{inode}. Nel
+caso di link simbolico cancella il link simbolico; nel caso di
+socket\index{socket}, fifo o file di dispositivo\index{file!di dispositivo}
+rimuove il nome, ma come per i file i processi che hanno aperto uno di questi
+oggetti possono continuare ad utilizzarlo.
+
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 sulla directory che la contiene (torneremo in
-dettaglio sui permessi e gli attributi in \secref{sec:file_access_control}),
-se inoltre lo \textit{sticky} bit è impostato occorrerà anche essere
-proprietari del file o proprietari della directory (o root, per cui nessuna
-delle restrizioni è applicata).
+scrittura su di essa, dato che si va a rimuovere una voce dal suo contenuto, e
+il diritto di esecuzione sulla directory che la contiene (affronteremo in
+dettaglio l'argomento dei permessi di file e directory in
+\secref{sec:file_access_control}). Se inoltre lo \textit{sticky} bit (vedi
+\secref{sec:file_sticky}) è impostato occorrerà anche essere proprietari del
+file o proprietari della directory (o root, per cui nessuna delle restrizioni
+è applicata).
Una delle caratteristiche di queste funzioni è che la creazione/rimozione del
nome dalla directory e l'incremento/decremento del numero di riferimenti
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
+Si ricordi infine che un file non viene eliminato dal disco fintanto che tutti
i riferimenti ad esso sono stati cancellati: solo quando il \textit{link
- count} mantenuto nell'inode\index{inode} diventa zero lo spazio occupato
-viene rimosso. A questo però si aggiunge un'altra condizione, e cioè che non
-ci siano processi che abbiano detto file aperto.
+ count} mantenuto nell'inode\index{inode} diventa zero lo spazio occupato su
+disco viene rimosso (si ricordi comunque che a questo si aggiunge sempre
+un'ulteriore condizione,\footnote{come vedremo in
+ \secref{cha:file_unix_interface} il kernel mantiene anche una tabella dei
+ file aperti nei vari processi, che a sua volta contiene i riferimenti agli
+ 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'inode in questione.} e cioè che non ci siano processi che abbiano il
+suddetto file aperto).
Questa proprietà viene spesso usata per essere sicuri di non lasciare file
temporanei su disco in caso di crash dei programmi; la tecnica è quella di
Al contrario di quanto avviene con altri Unix, in Linux non è possibile usare
\func{unlink} sulle directory; per cancellare una directory si può usare la
funzione \func{rmdir} (vedi \secref{sec:file_dir_creat_rem}), oppure la
-funzione \func{remove}. Questa è la funzione prevista dallo standard ANSI C
-per cancellare un file o una directory (e funziona anche per i sistemi che non
-supportano i link diretti). Per i file è identica a \func{unlink} e per le
-directory è identica a \func{rmdir}:
+funzione \func{remove}.
+
+Questa è la funzione prevista dallo standard ANSI C per cancellare un file o
+una directory (e funziona anche per i sistemi che non supportano i link
+diretti). Per i file è identica a \func{unlink} e per le directory è identica
+a \func{rmdir}; il suo prototipo è:
\begin{prototype}{stdio.h}{int remove(const char *pathname)}
- Cancella un nome dal filesystem. Usa \func{unlink} per i file e
- \func{rmdir} per le directory.
+ Cancella un nome dal filesystem.
\bodydesc{La funzione restituisce zero in caso di successo e -1 per un
- errore, nel qual caso il file non viene toccato. Per i codici di
- errore vedi quanto riportato nelle descrizioni di \func{unlink} e
- \func{rmdir}.}
+ errore, nel qual caso il file non viene toccato.
+
+ I codici di errore riportati in \var{errno} sono quelli della chiamata
+ utilizzata, pertanto si può fare riferimento a quanto illustrato nelle
+ descrizioni di \func{unlink} e \func{rmdir}.}
\end{prototype}
+La funzione utilizza la funzione \func{unlink}\footnote{questo vale usando le
+ \acr{glibc}; nelle libc4 e nelle libc5 la funzione \func{remove} è un
+ semplice alias alla funzione \func{unlink} e quindi non può essere usata per
+ le directory.} per cancellare i file e la funzione \func{rmdir} per
+cancellare le directory; si tenga presente che per alcune implementazioni del
+protocollo NFS utilizzare questa funzione può comportare la scomparsa di file
+ancora in uso.
+
Per cambiare nome ad un file o a una directory (che devono comunque essere
nello stesso filesystem) si usa invece la funzione \func{rename},\footnote{la
- funzione è definita dallo standard ANSI C solo per i file, POSIX estende la
- funzione anche alle directory.} il cui prototipo è:
+ funzione è definita dallo standard ANSI C, ma si applica solo per i file, lo
+ standard POSIX estende la funzione anche alle directory.} il cui prototipo
+è:
\begin{prototype}{stdio.h}
{int rename(const char *oldpath, const char *newpath)}
- Rinomina \var{oldpath} in \var{newpath}, eseguendo se necessario lo
- spostamento di un file fra directory diverse. Eventuali altri link diretti
- allo stesso file non vengono influenzati.
+ Rinomina un file.
\bodydesc{La funzione restituisce zero in caso di successo e -1 per un
errore, nel qual caso il file non viene toccato. La variabile
\var{errno} viene impostata secondo i seguenti codici di errore:
\begin{errlist}
- \item[\errcode{EISDIR}] \var{newpath} è una directory mentre \var{oldpath}
- non è una directory.
- \item[\errcode{EXDEV}] \var{oldpath} e \var{newpath} non sono sullo stesso
- filesystem.
- \item[\errcode{ENOTEMPTY}] \var{newpath} è una directory già esistente e non
- vuota.
- \item[\errcode{EBUSY}] o \var{oldpath} o \var{newpath} sono in uso da parte
- di qualche processo (come directory di lavoro o come radice) o del sistema
- (come mount point).
- \item[\errcode{EINVAL}] \var{newpath} contiene un prefisso di \var{oldpath} o
- più in generale si è cercato di creare una directory come sottodirectory
- di se stessa.
+ \item[\errcode{EISDIR}] \param{newpath} è una directory mentre
+ \param{oldpath} non è una directory.
+ \item[\errcode{EXDEV}] \param{oldpath} e \param{newpath} non sono sullo
+ stesso filesystem.
+ \item[\errcode{ENOTEMPTY}] \param{newpath} è una directory già esistente e
+ non vuota.
+ \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
+ sistema (come mount point).
+ \item[\errcode{EINVAL}] \param{newpath} contiene un prefisso di
+ \param{oldpath} o più in generale si è cercato di creare una directory come
+ sottodirectory di se stessa.
\item[\errcode{ENOTDIR}] Uno dei componenti dei pathname non è una directory
- o \var{oldpath} è una directory e \var{newpath} esiste e non è una
+ o \param{oldpath} è una directory e \param{newpath} esiste e non è una
directory.
\end{errlist}
ed inoltre \errval{EACCES}, \errval{EPERM}, \errval{EMLINK},
\errval{ENOSPC}.}
\end{prototype}
+La funzione rinomina il file \param{oldpath} in \param{newpath}, eseguendo se
+necessario lo spostamento di un file fra directory diverse. Eventuali altri
+link diretti allo stesso file non vengono influenzati.
+
Il comportamento della funzione è diverso a seconda che si voglia rinominare
-un file o una directory; se ci riferisce a un file allora \var{newpath}, se
+un file o una directory; se ci riferisce a un file allora \param{newpath}, se
esiste, non deve essere una directory (altrimenti si ha l'errore
-\errcode{EISDIR}). Nel caso \var{newpath} indichi un file esistente questo
+\errcode{EISDIR}). Nel caso \param{newpath} indichi un file esistente questo
viene cancellato e rimpiazzato (atomicamente).
-Se \var{oldpath} è una directory allora \var{newpath}, se esiste, deve essere
-una directory vuota, altrimenti si avranno gli errori \errcode{ENOTDIR} (se
-non è una directory) o \errcode{ENOTEMPTY} (se non è vuota). Chiaramente
-\var{newpath} non può contenere \var{oldpath} altrimenti si avrà un errore
+Se \param{oldpath} è una directory allora \param{newpath}, se esiste, deve
+essere una directory vuota, altrimenti si avranno gli errori \errcode{ENOTDIR}
+(se non è una directory) o \errcode{ENOTEMPTY} (se non è vuota). Chiaramente
+\param{newpath} non può contenere \param{oldpath} altrimenti si avrà un errore
\errcode{EINVAL}.
-Se \var{oldpath} si riferisce a un link simbolico questo sarà rinominato; se
-\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 \textit{glibc}, il comportamento più ragionevole
-sarebbe quello di cancellare \var{oldpath}.
+Se \param{oldpath} si riferisce a un link simbolico questo sarà rinominato; se
+\param{newpath} è un link simbolico verrà cancellato come qualunque altro
+file. Infine qualora \param{oldpath} e \param{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 \textit{glibc}, il comportamento più
+ragionevole sarebbe quello di cancellare \param{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
esistente, non trovare quest'ultimo prima che la sostituzione sia stata
eseguita.
-In ogni caso se \var{newpath} esiste e l'operazione fallisce per un qualche
+In ogni caso se \param{newpath} esiste e l'operazione fallisce per un qualche
motivo (come un crash del kernel), \func{rename} garantisce di lasciare
-presente un'istanza di \var{newpath}. Tuttavia nella sovrascrittura potrà
-esistere una finestra in cui sia \var{oldpath} che \var{newpath} fanno
+presente un'istanza di \param{newpath}. Tuttavia nella sovrascrittura potrà
+esistere una finestra in cui sia \param{oldpath} che \param{newpath} fanno
riferimento allo stesso file.
la funzione \func{readlink}, il cui prototipo è:
\begin{prototype}{unistd.h}
{int readlink(const char *path, char *buff, size\_t size)}
- Legge il contenuto del link simbolico indicato da \var{path} nel buffer
- \var{buff} di dimensione \var{size}.
+ Legge il contenuto del link simbolico indicato da \param{path} nel buffer
+ \param{buff} di dimensione \param{size}.
\bodydesc{La funzione restituisce il numero di caratteri letti dentro
- \var{buff} o -1 per un errore, nel qual caso la variabile
+ \param{buff} o -1 per un errore, nel qual caso la variabile
\var{errno} assumerà i valori:
\begin{errlist}
\item[\errcode{EINVAL}] \param{path} non è un link simbolico o \param{size}
La funzione apre il link simbolico, ne legge il contenuto, lo scrive nel
buffer, e lo richiude. Si tenga presente che la funzione non termina la
stringa con un carattere nullo e la tronca alla dimensione specificata da
-\var{size} per evitare di sovrascrivere oltre le dimensioni del buffer.
+\param{size} per evitare di sovrascrivere oltre le dimensioni del buffer.
\begin{figure}[htb]
accedere ai tipi usati da queste funzioni si deve includere il file
\file{sys/types.h}, il prototipo della prima è:
\begin{prototype}{sys/stat.h}
- {int mkdir(const char *dirname, mode\_t mode)}
- Crea una nuova directory vuota con il nome indicato da \var{dirname},
- assegnandole i permessi indicati da \var{mode}. Il nome può essere indicato
- con il pathname assoluto o relativo.
+ {int mkdir(const char *dirname, mode\_t mode)} Crea una nuova directory.
\bodydesc{La funzione restituisce zero in caso di successo e -1 per un
errore, nel qual caso \var{errno} assumerà i valori:
\errval{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
-valori sono riportati in \tabref{tab:file_permission_const}) sono modificati
-dalla maschera di creazione dei file (si veda \secref{sec:file_umask}). La
-titolarità della nuova directory è impostata secondo quanto riportato in
+La funzione crea una nuova directory vuota, che contiene cioè solo le due voci
+standard \file{.} e \file{..}, con il nome indicato dall'argomento
+\param{dirname}. Il nome può essere indicato sia come pathname assoluto che
+relativo.
+
+I permessi di accesso alla directory (vedi \secref{sec:file_access_control})
+sono specificati da \param{mode}, i cui possibili valori sono riportati in
+\tabref{tab:file_permission_const}; questi sono modificati dalla maschera di
+creazione dei file (si veda \secref{sec:file_umask}). La titolarità della
+nuova directory è impostata secondo quanto riportato in
\secref{sec:file_ownership}.
La seconda funzione serve ad eliminare una directory già vuota (la directory
deve cioè contenere soltanto le due voci standard \file{.} e \file{..}); il
suo prototipo è:
\begin{prototype}{sys/stat.h}{int rmdir(const char *dirname)}
- Cancella la directory \var{dirname}, che deve essere vuota. Il nome può
- essere indicato con il pathname assoluto o relativo.
-
+ Cancella una directory.
+
\bodydesc{La funzione restituisce zero in caso di successo e -1 per un
errore, nel qual caso \var{errno} assumerà i valori:
\begin{errlist}
\item[\errcode{EPERM}] Il filesystem non supporta la cancellazione di
- directory, oppure la directory che contiene \var{dirname} ha lo sticky bit
- impostato e l'userid effettivo del processo non corrisponde al
+ directory, oppure la directory che contiene \param{dirname} ha lo sticky
+ bit impostato e l'userid effettivo del processo non corrisponde al
proprietario della directory.
\item[\errcode{EACCES}] Non c'è il permesso di scrittura per la directory
che contiene la directory che si vuole cancellare, o non c'è il permesso
di attraversare (esecuzione) una delle directory specificate in
- \var{dirname}.
+ \param{dirname}.
\item[\errcode{EBUSY}] La directory specificata è la directory di lavoro o la
radice di qualche processo.
\item[\errcode{ENOTEMPTY}] La directory non è vuota.
\errval{ENOTDIR}, \errval{ENOMEM}, \errval{ELOOP}, \errval{EROFS}.}
\end{prototype}
+La funzione cancella la directory \param{dirname}, che deve essere vuota. Il
+nome può essere indicato con il pathname assoluto o relativo.
+
La modalità con cui avviene la cancellazione è analoga a quella di
\func{unlink}: fintanto che il numero di link all'inode\index{inode} della
directory non diventa nullo e nessun processo ha la directory aperta lo spazio
La manipolazione delle caratteristiche di questi file e la loro cancellazione
può essere effettuata con le stesse funzioni che operano sui file regolari; ma
quando li si devono creare sono necessarie delle funzioni apposite. La prima
-di queste funzioni è \func{mknod}, il suo prototipo è:
+di queste funzioni è \funcd{mknod}, il suo prototipo è:
\begin{functions}
\headdecl{sys/types.h}
\headdecl{sys/stat.h}
\headdecl{fnctl.h}
\headdecl{unistd.h}
- \funcdecl{int mknod(const char *pathname, mode\_t mode, dev\_t dev)} Crea un
- inode, si usa per creare i file speciali.
+ \funcdecl{int mknod(const char *pathname, mode\_t mode, dev\_t dev)}
+
+ Crea un inode, si usa per creare i file speciali.
\bodydesc{La funzione restituisce zero in caso di successo e -1 per un
errore, nel qual caso \var{errno} assumerà i valori:
\item[\errcode{EPERM}] Non si hanno privilegi sufficienti a creare l'inode, o
il filesystem su cui si è cercato di creare \func{pathname} non supporta
l'operazione.
- \item[\errcode{EINVAL}] Il valore di \var{mode} non indica un file, una fifo
- o un dipositivo.
+ \item[\errcode{EINVAL}] Il valore di \param{mode} non indica un file, una
+ fifo o un dipositivo.
\item[\errcode{EEXIST}] \param{pathname} esiste già o è un link simbolico.
\end{errlist}
ed inoltre anche \errval{EFAULT}, \errval{EACCES}, \errval{ENAMETOOLONG},
Per creare una fifo (un file speciale, su cui torneremo in dettaglio in
\secref{sec:ipc_named_pipe}) lo standard POSIX specifica l'uso della funzione
-\func{mkfifo}, il cui prototipo è:
+\funcd{mkfifo}, il cui prototipo è:
\begin{functions}
\headdecl{sys/types.h} \headdecl{sys/stat.h}
- \funcdecl{int mkfifo(const char *pathname, mode\_t mode)} Crea una fifo.
+ \funcdecl{int mkfifo(const char *pathname, mode\_t mode)}
+
+ Crea una fifo.
\bodydesc{La funzione restituisce zero in caso di successo e -1 per un
errore, nel qual caso \var{errno} assumerà i valori \errval{EACCES},
\label{sec:file_dir_read}
Benché le directory siano oggetti del filesystem come tutti gli altri non ha
-ovviamente senso aprirle come fossero dei file di dati. Può però essere utile
-poterne leggere il contenuto ad esempio per fare la lista dei file che esse
-contengono o ricerche sui medesimi. Solo il kernel può scrivere direttamente
-in una directory (onde evitare inconsistenze all'interno del filesystem), i
+senso aprirle come fossero dei file di dati. Inoltre si
+
+ Può però essere utile poterne
+leggere il contenuto ad esempio per fare la lista dei file che esse contengono
+o ricerche sui medesimi. Solo il kernel può scrivere direttamente il contenuto
+di una directory (onde evitare inconsistenze all'interno del filesystem), i
processi devono creare i file usando le apposite funzioni.
Per accedere al contenuto delle directory si usano i cosiddetti
\textit{directory streams} (chiamati così per l'analogia con i file stream di
-\capref{cha:files_std_interface}); la funzione \func{opendir} apre uno di
-questi stream e la funzione \func{readdir} legge il contenuto della directory,
-i cui elementi sono le \textit{directory entry} (da distinguersi da quelle
-della cache di cui parlavamo in \secref{sec:file_vfs}) in un'opportuna
-struttura \var{struct dirent}.
+\capref{cha:files_std_interface}); la funzione \funcd{opendir} apre uno di
+questi stream, il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h} \headdecl{dirent.h}
+
+ \funcdecl{DIR * opendir(const char *name)}
+
+ Apre un \textit{directory stream}.
+
+ \bodydesc{La funzione restituisce un puntatore al \textit{directory stream}
+ in caso di successo e \val{NULL} per un errore, nel qual caso \var{errno}
+ assumerà i valori \errval{EACCES}, \errval{EMFILE}, \errval{ENFILE},
+ \errval{ENOENT}, \errval{ENOMEM} e \errval{ENOTDIR}.}
+\end{functions}
+
+La funzione apre un \textit{directory stream} per la directory indicata da
+\param{name}, ritornando il puntatore allo stesso, e posizionandosi sulla
+prima voce della directory.
+
+Dato che le directory sono comunque dei file, in alcuni casi può essere utile
+conoscere il file descriptor sottostante un \textit{directory stream}, ad
+esempio per utilizzarlo con la funzione \func{fchdir} per cambiare la
+directory di lavoro (vedi \secref{sec:file_work_dir}) a quella relativa allo
+stream che si è aperto. A questo scopo si può usare la funzione \funcd{dirfd},
+il cui prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h} \headdecl{dirent.h}
+
+ \funcdecl{int dirfd(DIR * dir)}
+
+ Restituisce il file descriptor associato ad un \textit{directory stream}.
+
+ \bodydesc{La funzione restituisce il file descriptor (un valore positivo) in
+ caso di successo e -1 in caso di errore.}
+\end{functions}
+
+La funzione\footnote{questa funzione è una estensione di BSD introdotta con
+ BSD 4.3-Reno; è presente in Linux con le libc5 (a partire dalla versione
+ 5.1.2) e con le \acr{glibc}.} restituisce il file descriptor associato al
+\textit{directory stream} \param{dir}, essa è disponibile solo definendo
+\macro{\_BSD\_SOURCE} o \macro{\_SVID\_SOURCE}.
+
+
+
+La funzione \func{readdir} legge il contenuto della directory, i cui elementi
+sono le \textit{directory entry} (da distinguersi da quelle della cache di cui
+parlavamo in \secref{sec:file_vfs}) in un'opportuna struttura \struct{dirent}
+definita in \figref{fig:file_dirent_struct}.
+
+
+\begin{figure}[!htb]
+ \footnotesize
+ \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+struct dirent {
+ ino_t d_ino;
+ unsigned short int d_reclen;
+ unsigned char d_type;
+ char d_name[256]; /* We must not include limits.h! */
+};
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \structd{dirent} per la lettura delle informazioni dei
+ file.}
+ \label{fig:file_dirent_struct}
+\end{figure}
+
-(NdA Il resto va scritto!!! É noioso e lo farò più avanti).
\subsection{La directory di lavoro}
apposita funzione di libreria, \func{getcwd}, il cui prototipo è:
\begin{prototype}{unistd.h}{char *getcwd(char *buffer, size\_t size)}
Restituisce il filename completo della directory di lavoro corrente nella
- stringa puntata da \var{buffer}, che deve essere precedentemente
- allocata, per una dimensione massima di \var{size}.
+ stringa puntata da \param{buffer}, che deve essere precedentemente allocata,
+ per una dimensione massima di \param{size}.
- \bodydesc{La funzione restituisce il puntatore \var{buffer} se riesce,
+ \bodydesc{La funzione restituisce il puntatore \param{buffer} se riesce,
\val{NULL} se fallisce, in quest'ultimo caso la variabile
\var{errno} è impostata con i seguenti codici di errore:
\begin{errlist}
- \item[\errcode{EINVAL}] L'argomento \var{size} è zero e \var{buffer} non
+ \item[\errcode{EINVAL}] L'argomento \param{size} è zero e \param{buffer} non
è nullo.
- \item[\errcode{ERANGE}] L'argomento \var{size} è più piccolo della
+ \item[\errcode{ERANGE}] L'argomento \param{size} è più piccolo della
lunghezza del pathname.
\item[\errcode{EACCES}] Manca il permesso di lettura o di ricerca su uno dei
componenti del pathname (cioè su una delle directory superiori alla
Il buffer deve essere sufficientemente lungo da poter contenere il pathname
completo più lo zero di terminazione della stringa. Qualora esso ecceda le
-dimensioni specificate con \var{size} la funzione restituisce un errore. Si
-può anche specificare un puntatore nullo come \var{buffer},\footnote{questa è
+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.} nel qual caso la
-stringa sarà allocata automaticamente per una dimensione pari a \var{size}
+stringa sarà allocata automaticamente per una dimensione pari a \param{size}
qualora questa sia diversa da zero, o della lunghezza esatta del pathname
altrimenti. In questo caso ci si deve ricordare di disallocare la stringa una
volta cessato il suo utilizzo.
\label{sec:file_stat}
La lettura delle informazioni relative ai file è fatta attraverso la famiglia
-delle funzioni \func{stat}; questa è la funzione che ad esempio usa il comando
-\cmd{ls} per poter ottenere e mostrare tutti i dati dei files. I prototipi di
-queste funzioni sono i seguenti:
+delle funzioni \func{stat} (\funcd{stat}, \funcd{fstat} e \funcd{lstat});
+questa è la funzione che ad esempio usa il comando \cmd{ls} per poter ottenere
+e mostrare tutti i dati dei files. I prototipi di queste funzioni sono i
+seguenti:
\begin{functions}
\headdecl{sys/types.h}
\headdecl{sys/stat.h}
\headdecl{unistd.h}
\funcdecl{int stat(const char *file\_name, struct stat *buf)} Legge le
- informazione del file specificato da \var{file\_name} e le inserisce in
- \var{buf}.
+ informazione del file specificato da \param{file\_name} e le inserisce in
+ \param{buf}.
\funcdecl{int lstat(const char *file\_name, struct stat *buf)} Identica a
- \func{stat} eccetto che se il \var{file\_name} è un link simbolico vengono
+ \func{stat} eccetto che se il \param{file\_name} è un link simbolico vengono
lette le informazioni relativa ad esso e non al file a cui fa riferimento.
\funcdecl{int fstat(int filedes, struct stat *buf)} Identica a \func{stat}
eccetto che si usa con un file aperto, specificato tramite il suo file
- descriptor \var{filedes}.
+ descriptor \param{filedes}.
\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 per un
errore, nel qual caso \var{errno} assumerà uno dei valori: \errval{EBADF},
\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} usata da queste funzioni è definita nell'header
+La struttura \struct{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 \figref{fig:file_stat_struct}, così come
riportata dalla pagina di manuale di \func{stat} (in realtà la definizione
\end{lstlisting}
\end{minipage}
\normalsize
- \caption{La struttura \var{stat} per la lettura delle informazioni dei
- file}
+ \caption{La struttura \structd{stat} per la lettura delle informazioni dei
+ file.}
\label{fig:file_stat_struct}
\end{figure}
\subsection{Le dimensioni dei file}
\label{sec:file_file_size}
-Il membro \var{st\_size} contiene la dimensione del file in byte (se si tratta
+Il campo \var{st\_size} contiene la dimensione del file in byte (se si tratta
di un file regolare, nel caso di un link simbolico la dimensione è quella del
pathname che contiene, per le fifo è sempre nullo).
Un file può sempre essere troncato a zero aprendolo con il flag
\const{O\_TRUNC}, ma questo è un caso particolare; per qualunque altra
-dimensione si possono usare le due funzioni \func{truncate} e
-\func{ftruncate}, i cui prototipi sono:
+dimensione si possono usare le due funzioni \funcd{truncate} e
+\funcd{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
- un valore massimo specificato da \var{lenght}.
+ length)} Fa si che la dimensione del file \param{file\_name} sia troncata
+ ad un valore massimo specificato da \param{lenght}.
\funcdecl{int ftruncate(int fd, off\_t length))} Identica a \func{truncate}
eccetto che si usa con un file aperto, specificato tramite il suo file
- descriptor \var{fd}.
+ descriptor \param{fd}.
\bodydesc{Le funzioni restituiscono zero in caso di successo e -1 per un
errore, nel qual caso \var{errno} viene impostata opportunamente; per
\func{ftruncate} si hanno i valori:
\begin{errlist}
- \item[\errcode{EBADF}] \var{fd} non è un file descriptor.
- \item[\errcode{EINVAL}] \var{fd} è un riferimento ad un
+ \item[\errcode{EBADF}] \param{fd} non è un file descriptor.
+ \item[\errcode{EINVAL}] \param{fd} è un riferimento ad un
socket\index{socket}, non a un file o non è aperto in scrittura.
\end{errlist}
per \func{truncate} si hanno:
Il sistema mantiene per ciascun file tre tempi. Questi sono registrati
nell'inode\index{inode} insieme agli altri attributi del file e possono essere
letti tramite la funzione \func{stat}, che li restituisce attraverso tre campi
-della struttura \var{stat} di \figref{fig:file_stat_struct}. Il significato di
-detti tempi e dei relativi campi è riportato nello schema in
+della struttura \struct{stat} di \figref{fig:file_stat_struct}. Il significato
+di detti tempi e dei relativi campi è riportato nello schema in
\tabref{tab:file_file_times}, dove è anche riportato un esempio delle funzioni
che effettuano cambiamenti su di essi.
\item[\errcode{ENOENT}] \param{filename} non esiste.
\end{errlist}}
\end{prototype}
-
-La funzione prende come argomento \param{times} una struttura \var{utimebuf},
-la cui definizione è riportata in \figref{fig:struct_utimebuf}, con la quale
-si possono specificare i nuovi valori che si vogliono impostare per tempi.
+
+La funzione prende come argomento \param{times} una struttura
+\struct{utimebuf}, la cui definizione è riportata in
+\figref{fig:struct_utimebuf}, con la quale si possono specificare i nuovi
+valori che si vogliono impostare per tempi.
\begin{figure}[!htb]
\footnotesize \centering
\end{lstlisting}
\end{minipage}
\normalsize
- \caption{La struttura \type{utimbuf}, usata da \func{utime} per modificare i
- tempi dei file.}
+ \caption{La struttura \structd{utimbuf}, usata da \func{utime} per modificare
+ i tempi dei file.}
\label{fig:struct_utimebuf}
\end{figure}
cosiddetto \textit{owner}) ed un gruppo di appartenenza, secondo il meccanismo
degli identificatori di utente e gruppo (\acr{uid} e \acr{gid}). Questi valori
sono accessibili da programma tramite la funzione \func{stat}, e sono
-mantenuti nei campi \var{st\_uid} e \var{st\_gid} della struttura \var{stat}
-(si veda \secref{sec:file_stat}).\footnote{Questo è vero solo per filesystem
- di tipo Unix, ad esempio non è vero per il filesystem vfat di Windows, che
- non fornisce nessun supporto per l'accesso multiutente, e per il quale i
- permessi vengono assegnati in maniera fissa con un opzione in fase di
- montaggio.}
+mantenuti nei campi \var{st\_uid} e \var{st\_gid} della struttura
+\struct{stat} (si veda \secref{sec:file_stat}).\footnote{Questo è vero solo
+ per filesystem di tipo Unix, ad esempio non è vero per il filesystem vfat di
+ Windows, che non fornisce nessun supporto per l'accesso multiutente, e per
+ il quale i permessi vengono assegnati in maniera fissa con un opzione in
+ fase di montaggio.}
Il controllo di accesso ai file segue un modello abbastanza semplice che
prevede tre permessi fondamentali strutturati su tre livelli di accesso.
\centering
\includegraphics[width=6cm]{img/fileperm}
\caption{Lo schema dei bit utilizzati per specificare i permessi di un file
- contenuti nel campo \var{st\_mode} di \var{fstat}.}
+ contenuti nel campo \var{st\_mode} di \struct{fstat}.}
\label{fig:file_perm_bit}
\end{figure}
Anche i permessi, come tutte le altre informazioni pertinenti al file, sono
memorizzati nell'inode\index{inode}; in particolare essi sono contenuti in
-alcuni bit del campo \var{st\_mode} della struttura \func{stat} (si veda di
+alcuni bit del campo \var{st\_mode} della struttura \struct{stat} (si veda di
nuovo \figref{fig:file_stat_struct}).
In genere ci si riferisce ai tre livelli dei privilegi usando le lettere
\label{sec:file_suid_sgid}
Come si è accennato (in \secref{sec:file_perm_overview}) nei dodici bit del
-campo \var{st\_mode} di \var{stat} che vengono usati per il controllo di
+campo \var{st\_mode} di \struct{stat} che vengono usati per il controllo di
accesso oltre ai bit dei permessi veri e propri, ci sono altri tre bit che
vengono usati per indicare alcune proprietà speciali dei file. Due di questi
sono i bit detti \acr{suid} (da \textit{set-user-ID bit}) e \acr{sgid} (da
\tabref{tab:file_access_mode_val} (attraverso un OR binario delle stesse). I
primi tre valori implicano anche la verifica dell'esistenza del file, se si
vuole verificare solo quest'ultima si può usare \const{F\_OK}, o anche
-direttamente \func{stat}. Nel caso in cui \var{pathname} si riferisca ad un
+direttamente \func{stat}. Nel caso in cui \param{pathname} si riferisca ad un
link simbolico, questo viene seguito ed il controllo è fatto sul file a cui
esso fa riferimento.
\footnotesize
\begin{tabular}{|c|l|}
\hline
- \textbf{\var{mode}} & \textbf{Significato} \\
+ \textbf{\param{mode}} & \textbf{Significato} \\
\hline
\hline
\const{R\_OK} & verifica il permesso di lettura \\
\const{F\_OK} & verifica l'esistenza del file \\
\hline
\end{tabular}
- \caption{Valori possibile per il parametro \var{mode} della funzione
+ \caption{Valori possibile per l'argomento \param{mode} della funzione
\func{access}.}
\label{tab:file_access_mode_val}
\end{table}
\label{sec:file_chmod}
Per cambiare i permessi di un file il sistema mette ad disposizione due
-funzioni \func{chmod} e \func{fchmod}, che operano rispettivamente su un
+funzioni \funcd{chmod} e \funcd{fchmod}, che operano rispettivamente su un
filename e su un file descriptor, i loro prototipi sono:
\begin{functions}
\headdecl{sys/types.h}
\headdecl{sys/stat.h}
\funcdecl{int chmod(const char *path, mode\_t mode)} Cambia i permessi del
- file indicato da \var{path} al valore indicato da \var{mode}.
+ file indicato da \param{path} al valore indicato da \param{mode}.
\funcdecl{int fchmod(int fd, mode\_t mode)} Analoga alla precedente, ma usa
- il file descriptor \var{fd} per indicare il file.
+ il file descriptor \param{fd} per indicare il file.
\bodydesc{Le funzioni restituiscono zero in caso di successo e -1 per
un errore, in caso di errore \var{errno} può assumere i valori:
\footnotesize
\begin{tabular}[c]{|c|c|l|}
\hline
- \textbf{\var{mode}} & \textbf{Valore} & \textbf{Significato} \\
+ \textbf{\param{mode}} & \textbf{Valore} & \textbf{Significato} \\
\hline
\hline
\const{S\_ISUID} & 04000 & set user ID \\
\begin{prototype}{stat.h}
{mode\_t umask(mode\_t mask)}
- Imposta la maschera dei permessi dei bit al valore specificato da \var{mask}
- (di cui vengono presi solo i 9 bit meno significativi).
+Imposta la maschera dei permessi dei bit al valore specificato da \param{mask}
+(di cui vengono presi solo i 9 bit meno significativi).
\bodydesc{La funzione ritorna il precedente valore della maschera. È una
delle poche funzioni che non restituisce codici di errore.}
\end{prototype}
Questa maschera è una caratteristica di ogni processo\footnote{è infatti
- contenuta nel campo \var{umask} di \var{fs\_struct}, vedi
+ contenuta nel campo \param{umask} di \struct{fs\_struct}, vedi
\figref{fig:proc_task_struct}.} e viene utilizzata per impedire che alcuni
permessi possano essere assegnati ai nuovi file in sede di creazione. I bit
indicati nella maschera vengono infatti esclusi quando un nuovo file viene
Come per i permessi, il sistema fornisce anche delle funzioni che permettano
di cambiare utente e gruppo cui il file appartiene; le funzioni in questione
-sono tre e i loro prototipi sono i seguenti:
+sono tre: \funcd{chown}, \funcd{fchown} e \funcd{lchown}, ed i loro prototipi
+sono:
\begin{functions}
\headdecl{sys/types.h}
\headdecl{sys/stat.h}
\funcdecl{int lchown(const char *path, uid\_t owner, gid\_t group)}
Le funzioni cambiano utente e gruppo di appartenenza di un file ai valori
- specificati dalle variabili \var{owner} e \var{group}.
+ specificati dalle variabili \param{owner} e \param{group}.
\bodydesc{Le funzioni restituiscono zero in caso di successo e -1 per
un errore, in caso di errore \var{errno} può assumere i valori:
\func{chown} che seguisse i link simbolici.} La funzione \func{fchown} opera
su un file aperto, essa è mutuata da BSD, ma non è nello standard POSIX.
Un'altra estensione rispetto allo standard POSIX è che specificando -1 come
-valore per \var{owner} e \var{group} i valori restano immutati.
+valore per \param{owner} e \param{group} i valori restano immutati.
Quando queste funzioni sono chiamate con successo da un processo senza i
privilegi di root entrambi i bit \acr{suid} e \acr{sgid} vengono
Come accennato in \secref{sec:proc_fork} ogni processo oltre ad una directory
di lavoro corrente, ha anche una directory radice,\footnote{entrambe sono
- contenute in due campi di \var{fs\_struct}, vedi
+ contenute in due campi di \struct{fs\_struct}, vedi
\figref{fig:proc_task_struct}.} 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