\textit{hard link}). Il prototipo della funzione e le sue caratteristiche
principali, come risultano dalla man page, sono le seguenti:
\begin{prototype}{unistd.h}
-{int link(const char * oldpath, const char * newpath)}
+{int link(const char *oldpath, const char *newpath)}
Crea un nuovo collegamento diretto al file indicato da \var{oldpath}
dandogli nome \var{newpath}.
La rimozione di un file (o più precisamente della voce che lo referenzia
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)}
+\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. Nel caso di link
simbolico cancella il link simbolico; nel caso di socket, fifo o file di
specificato. La funzione che permette di creare un nuovo link simbolico è
\func{symlink}; il suo prototipo è:
\begin{prototype}{unistd.h}
- {int symlink(const char * oldpath, const char * newpath)}
- Crea un nuovo link simbolico di nome \func{newpath} il cui contenuto è
- \func{oldpath}.
+ {int symlink(const char *oldpath, const char *newpath)}
+ Crea un nuovo link simbolico di nome \param{newpath} il cui contenuto è
+ \param{oldpath}.
\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 \var{newpath} non supporta i
+ \item[\macro{EPERM}] il filesystem che contiene \param{newpath} non supporta i
link simbolici.
- \item[\macro{ENOENT}] una componente di \var{newpath} non esiste o
- \func{oldpath} è una stringa vuota.
- \item[\macro{EEXIST}] esiste già un file \var{newpath}.
- \item[\macro{EROFS}] \var{newpath} è su un filesystem montato in sola
+ \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}.
+ \item[\macro{EROFS}] \param{newpath} è su un filesystem montato in sola
lettura.
\end{errlist}
ed inoltre \macro{EFAULT}, \macro{EACCES}, \macro{ENAMETOOLONG},
\end{prototype}
Si tenga presente che la funzione non effettua nessun controllo sull'esistenza
-di un file di nome \var{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}.
+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}.
Come accennato i link simbolici sono risolti automaticamente dal kernel
riferimento. Quando si vuole leggere il contenuto di un link simbolico si usa
la funzione \func{readlink}, il cui prototipo è:
\begin{prototype}{unistd.h}
-{int readlink(const char * path, char * buff, size\_t size)}
+{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}.
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},
-\file/{boot/boot/boot} e così via.
+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
mostrerebbe l'esistenza di \file{temporaneo}.
-\subsection{Le funzioni \func{mkdir} e \func{rmdir}}
+\subsection{La creazione e la cancellazione delle directory}
\label{sec:file_dir_creat_rem}
-Queste due funzioni servono per creare e cancellare delle directory e sono
-omonime degli analoghi comandi di shell. Per poter accedere ai tipi usati
-da queste funzioni si deve includere il file \file{sys/types.h}, il
-prototipo della prima è:
+Per creare e cancellare delle directory si usano le due funzioni (omonime
+degli analoghi comandi di shell) \func{mkdir} e \func{rmdir}. Per poter
+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)}
+ {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.
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.
+\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.
\bodydesc{La funzione restituisce zero in caso di successo e -1 per un
errore, nel qual caso \var{errno} assumerà i valori:
\end{prototype}
La modalità con cui avviene la cancellazione è analoga a quella di
-\func{unlink}, fintanto che il numero di link all'inode della directory non
+\func{unlink}: fintanto che il numero di link all'inode della directory non
diventa nullo e nessun processo ha la directory aperta lo spazio occupato su
disco non viene rilasciato. Se un processo ha la directory aperta la funzione
rimuove il link all'inode e nel caso sia l'ultimo, pure le voci standard
-\file{.} e \file{..}, ed il kernel non consentirà di creare più nuovi file
-nella directory.
+\file{.} e \file{..}, a questo punto il kernel non consentirà di creare più
+nuovi file nella directory.
+
+
+\subsection{La creazione di file speciali}
+\label{sec:file_mknod}
+
+Finora abbiamo parlato esclusivamente di file, directory e link simbolici; in
+\secref{sec:file_file_types} abbiamo visto però che il sistema preveda pure
+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
+può essere effettuata con le stesse funzioni che operano sui file normali; ma
+quando li si devono creare sono necessarie delle funzioni apposite.
+
+\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)}
+
+ \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[\macro{EPERM}] Il filesystem non supporta la cancellazione di
+ directory, oppure la directory che contiene \var{dirname} ha lo sticky bit
+ settato e l'\textit{effective user id} del processo non corrisponde al
+ proprietario della directory.
+ \item[\macro{EACCESS}] 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}.
+ \item[\macro{EBUSY}] La directory specificata è la directory di lavoro o la
+ radice di qualche processo.
+ \item[\macro{ENOTEMPTY}] La directory non è vuota.
+ \end{errlist}
+ ed inoltre anche \macro{EFAULT}, \macro{ENAMETOOLONG}, \macro{ENOENT},
+ \macro{ENOTDIR}, \macro{ENOMEM}, \macro{ELOOP}, \macro{EROFS}.}
+\end{functions}
+
+
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/stat.h}
+ \funcdecl{int mkfifo(const char *pathname, mode\_t mode)}
+
+ \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[\macro{EPERM}] Il filesystem non supporta la cancellazione di
+ directory, oppure la directory che contiene \var{dirname} ha lo sticky bit
+ settato e l'\textit{effective user id} del processo non corrisponde al
+ proprietario della directory.
+ \item[\macro{EACCESS}] 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}.
+ \item[\macro{EBUSY}] La directory specificata è la directory di lavoro o la
+ radice di qualche processo.
+ \item[\macro{ENOTEMPTY}] La directory non è vuota.
+ \end{errlist}
+ ed inoltre anche \macro{EFAULT}, \macro{ENAMETOOLONG}, \macro{ENOENT},
+ \macro{ENOTDIR}, \macro{ENOMEM}, \macro{ELOOP}, \macro{EROFS}.}
+\end{functions}
+
+
\subsection{Accesso alle directory}
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 scrivere direttamente in
-una directory (onde evitare inconsistenze all'interno del filesystem), i
+contengono o ricerche sui medesimi. Solo il kernel può scrivere direttamente
+in 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);
-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 una opportuna struttura \var{struct
- dirent}.
+\textit{directory streams} (chiamati così per l'analogia con i file stream di
+\capref{che:file_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 una opportuna
+struttura \var{struct dirent}.
(NdA Il resto va scritto!!! É noioso e lo farò più avanti).
In genere il kernel tiene traccia per ciascun processo dell'inode della
directory di lavoro corrente, per ottenere il pathname occorre usare una
apposita funzione di libreria, \func{getcwd}, il cui prototipo è:
-\begin{prototype}{unistd.h}{char * getcwd (char * buffer, size\_t size)}
+\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}.
altrimenti. In questo caso ci si deve ricordare di disallocare la stringa una
volta cessato il suo utilizzo.
-Di questa funzione esiste una versione \func{char * getwd(char * buffer)}
+Di questa funzione esiste una versione \code{char *getwd(char *buffer)}
fatta per compatibilità all'indietro con BSD, che non consente di specificare
la dimensione del buffer; esso deve essere allocato in precedenza ed avere una
dimensione superiore a \macro{PATH\_MAX} (di solito 256 byte, vedi
contenere il nome del file, e questa è la ragione principale per cui questa
funzione è deprecata.
-Una seconda funzione simile è \func{char * get\_current\_dir\_name(void)} che
-è sostanzialmente equivalente ad una \func{getcwd(NULL, 0)}, con la sola
+Una seconda funzione simile è \code{char *get\_current\_dir\_name(void)} che è
+sostanzialmente equivalente ad una \code{getcwd(NULL, 0)}, con la sola
differenza che essa ritorna il valore della variabile di ambiente \macro{PWD},
che essendo costruita dalla shell può contenere anche dei riferimenti
-simbolici; nel caso di \func{getcwd} infatti, essendo il pathname ricavato
+simbolici; nel caso di \func{getcwd} infatti, essendo il pathname ricavato
risalendo all'indietro l'albero della directory, si perderebbe traccia di ogni
passaggio attraverso eventuali pathname.
non solo tramite il filename, i prototipi di queste funzioni sono:
\begin{functions}
\headdecl{unistd.h}
- \funcdecl{int chdir (const char * path)}
+ \funcdecl{int chdir(const char *path)}
Cambia la directory di lavoro corrente a quella specificata dal pathname
contenuto nella stringa \var{path}.
- \funcdecl{int fchdir (int fd)} Analoga alla precedente, ma
- usa un file descriptor invece del pathname.
+ \funcdecl{int fchdir(int fd)} Analoga alla precedente, ma usa un file
+ descriptor invece del pathname.
\bodydesc{Entrambe le funzioni restituiscono zero in caso di successo
e -1 per un errore, in caso di errore \var{errno} viene settata per
\func{chdir} ai valori:
\begin{errlist}
- \item[\macro{ENOTDIR}] Uno dei componenti di \var{path} non è una directory.
+ \item[\macro{ENOTDIR}] Uno dei componenti di \param{path} non è una
+ directory.
\item[\macro{EACCESS}] Manca il permesso di ricerca su uno dei componenti di
- \func{path}.
+ \param{path}.
\end{errlist}
ed inoltre \macro{EFAULT}, \macro{ENAMETOOLONG}, \macro{ENOENT},
\macro{ENOMEM}, \macro{ELOOP} e \macro{EIO}. Per \func{fchdir} invece gli
+\subsection{I file temporanei}
+\label{sec:file_temp_file}
+
+Un'altra serie di funzioni definite dalle librerie standard del C sono quelle
+che riguardano la creazione di file temporanei.
+
+
+
+
\section{La manipolazione delle caratteristiche dei files}
\label{sec:file_infos}
che corrisponda all'occupazione dello spazio su disco per via della possibile
esistenza dei cosiddetti \textsl{buchi} (detti normalmente \textit{holes}) che
si formano tutte le volte che si va a scrivere su un file dopo aver eseguito
-una \func{seek} (vedi \secref{sec:file_lseek}) oltre la sua conclusione
+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
risultato di \cmd{ls}.
Se è sempre possibile allargare un file, scrivendoci sopra od usando la
-funzione \func{seek} per spostarsi oltre la sua fine, esistono anche casi in
+funzione \func{lseek} per spostarsi oltre la sua fine, esistono anche casi in
cui si può avere bisogno di effettuare un troncamento, scartando i dati
presenti al di là della dimensione scelta come nuova fine del file.
I tempi di ultimo accesso e modifica possono essere cambiati usando la
funzione \func{utime}, il cui prototipo è:
\begin{prototype}{utime.h}
-{int utime(const char * filename, struct utimbuf *times)}
+{int utime(const char *filename, struct utimbuf *times)}
Cambia i tempi di ultimo accesso e modifica dell'inode specificato da
-\var{filename} secondo i campi \var{actime} e \var{modtime} di \var{times}. Se
-questa è \macro{NULL} allora viene usato il tempo corrente.
+\param{filename} secondo i campi \var{actime} e \var{modtime} di
+\param{times}. Se questa è \macro{NULL} allora viene usato il tempo corrente.
\bodydesc{La funzione restituisce zero in caso di successo e -1 in caso
di errore, nel qual caso \var{errno} è settata opportunamente.
\begin{errlist}
\item[\macro{EACCESS}] non si ha il permesso di scrittura sul file.
-\item[\macro{ENOENT}] \var{filename} non esiste.
+\item[\macro{ENOENT}] \param{filename} non esiste.
\end{errlist}}
\end{prototype}
\end{lstlisting}
L'effetto della funzione e i privilegi necessari per eseguirla dipendono da
-cosa è l'argomento \var{times}; se è \macro{NULL} la funzione setta il tempo
+cosa è l'argomento \param{times}; se è \macro{NULL} la funzione setta il tempo
corrente ed è sufficiente avere accesso in scrittura al file; se invece si è
specificato un valore la funzione avrà successo solo se si è proprietari del
file (o si hanno i privilegi di amministratore).
I passi attraverso i quali viene stabilito se il processo possiede il diritto
di accesso sono i seguenti:
-\begin{itemize}
+\begin{enumerate}
\item Se l'\textit{effective user id} del processo è zero (corrispondente
all'amministratore) l'accesso è sempre garantito senza nessun ulteriore
controllo. Per questo motivo \textsl{root} ha piena libertà di accesso a
\item Se l'\textit{effective user id} del processo è uguale all'\acr{uid} del
proprietario del file (nel qual caso si dice che il processo è proprietario
del file) allora:
- \begin{itemize}
+ \begin{itemize*}
\item se il relativo\footnote{per relativo si intende il bit di user-read se
il processo vuole accedere in scrittura, quello di user-write per
l'accesso in scrittura, etc.} bit dei permessi d'accesso dell'utente è
settato, l'accesso è consentito
\item altrimenti l'accesso è negato
- \end{itemize}
+ \end{itemize*}
\item Se l'\textit{effective group id} del processo o uno dei
\textit{supplementary group id} dei processi corrispondono al \acr{gid} del
file allora:
- \begin{itemize}
+ \begin{itemize*}
\item se il bit dei permessi d'accesso del gruppo è settato, l'accesso è
consentito,
\item altrimenti l'accesso è negato
- \end{itemize}
+ \end{itemize*}
\item se il bit dei permessi d'accesso per tutti gli altri è settato,
l'accesso è consentito, altrimenti l'accesso è negato.
-\end{itemize}
+\end{enumerate}
Si tenga presente che questi passi vengono eseguiti esattamente in
quest'ordine. Questo vuol dire che se un processo è il proprietario di un file
la supporta, così come BSD e SVR4}, in questo caso se il bit è settato un
file potrà essere rimosso dalla directory soltanto se l'utente ha il permesso
di scrittura ed inoltre è vera una delle seguenti condizioni:
-\begin{itemize}
+\begin{itemize*}
\item l'utente è proprietario del file
\item l'utente è proprietario della directory
\item l'utente è l'amministratore
-\end{itemize}
+\end{itemize*}
un classico esempio di directory che ha questo bit settato è \file{/tmp}, i
permessi infatti di solito sono settati come:
\begin{verbatim}
Lo standard POSIX prescrive che l'\acr{uid} del nuovo file corrisponda
all'\textit{effective user id} del processo che lo crea; per il \acr{gid}
invece prevede due diverse possibilità:
-\begin{itemize}
+\begin{itemize*}
\item il \acr{gid} del file corrisponde all'\textit{effective group id} del
processo.
\item il \acr{gid} del file corrisponde al \acr{gid} della directory in cui
esso è creato.
-\end{itemize}
+\end{itemize*}
in genere BSD usa sempre la seconda possibilità, che viene per questo chiamata
semantica BSD. Linux invece segue quella che viene chiamata semantica SVr4; di
norma cioè il nuovo file viene creato, seguendo la prima opzione, con il
alcune limitazioni, provviste per motivi di sicurezza. Questo significa che
anche se si è proprietari del file non tutte le operazioni sono permesse, in
particolare:
-\begin{itemize}
+\begin{enumerate}
\item siccome solo l'amministratore può settare lo \textit{sticky bit}; se
l'\textit{effective user id} del processo non è zero esso viene
automaticamente cancellato (senza notifica di errore) qualora sia stato
notifica di errore) da \var{mode} qualora il gruppo del file non corrisponda
a quelli associati al processo (la cosa non avviene quando
l'\textit{effective user id} del processo è zero).
-\end{itemize}
+\end{enumerate}
Per alcuni filesystem\footnote{il filesystem \acr{ext2} supporta questa
caratteristica, che è mutuata da BSD.} è inoltre prevista una ulteriore
%completo vedi \ntab), i permessi (vedi \secref{sec:file_perms}), le date (vedi
%\secref{sec:file_times}).
-