+%% filedir.tex
+%%
+%% Copyright (C) 2000-2004 Simone Piccardi. Permission is granted to
+%% copy, distribute and/or modify this document under the terms of the GNU Free
+%% Documentation License, Version 1.1 or any later version published by the
+%% Free Software Foundation; with the Invariant Sections being "Un preambolo",
+%% with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the
+%% license is included in the section entitled "GNU Free Documentation
+%% License".
+%%
\chapter{File e directory}
\label{cha:files_and_dirs}
\section{La gestione di file e directory}
\label{sec:file_dir}
-Come già accennato in \secref{sec:file_filesystem} in un sistema unix-like la
+Come già accennato in sez.~\ref{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
-\secref{sec:file_arch_func}) ci sono due metodi sostanzialmente diversi per
+usualmente chiamati \textit{link}; ma data l'architettura del sistema riguardo
+la gestione dei file (ed in particolare quanto trattato in
+sez.~\ref{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; 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 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:
+Come spiegato in sez.~\ref{sec:file_filesystem} l'accesso al contenuto di un
+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, mantenuta all'interno della directory, 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, dati da altrettante diverse associazioni allo stesso
+inode\index{inode} di etichette diverse in directory diverse. Si noti anche
+che nessuno di questi nomi viene ad assumere una particolare preferenza o
+originalità rispetto agli altri, in quanto tutti fanno comunque riferimento
+allo stesso inode\index{inode}.
+
+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 è:
\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.
- \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[\macro{EXDEV}] \var{oldpath} e \var{newpath} non sono sullo
+ \item[\errcode{EXDEV}] \param{oldpath} e \param{newpath} non sono sullo
stesso filesystem.
- \item[\macro{EPERM}] il filesystem che contiene \var{oldpath} e
- \macro{newpath} non supporta i link diretti o è una directory.
- \item[\macro{EEXIST}] un file (o una directory) con quel nome esiste di
+ \item[\errcode{EPERM}] il filesystem che contiene \param{oldpath} e
+ \param{newpath} non supporta i link diretti o è una directory.
+ \item[\errcode{EEXIST}] un file (o una directory) con quel nome esiste di
già.
- \item[\macro{EMLINK}] ci sono troppi link al file \var{oldpath} (il
- numero massimo è specificato dalla variabile \macro{LINK\_MAX}, vedi
- \secref{sec:sys_limits}).
+ \item[\errcode{EMLINK}] ci sono troppi link al file \param{oldpath} (il
+ numero massimo è specificato dalla variabile \const{LINK\_MAX}, vedi
+ sez.~\ref{sec:sys_limits}).
\end{errlist}
- ed inoltre \macro{EACCES}, \macro{ENAMETOOLONG}, \macro{ENOTDIR},
- \macro{EFAULT}, \macro{ENOMEM}, \macro{EROFS}, \macro{ELOOP},
- \macro{ENOSPC}, \macro{EIO}.}
+ ed inoltre \errval{EACCES}, \errval{ENAMETOOLONG}, \errval{ENOTDIR},
+ \errval{EFAULT}, \errval{ENOMEM}, \errval{EROFS}, \errval{ELOOP},
+ \errval{ENOSPC}, \errval{EIO}.}
\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 referenze al file (riportato nel campo
-\var{st\_nlink} della struttura \var{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.
+La funzione crea sul \index{\textit{pathname}}\textit{pathname}
+\param{newpath} un collegamento diretto al file indicato da \param{oldpath}.
+Per quanto detto la creazione di un nuovo collegamento diretto non copia il
+contenuto del file, ma si limita a creare una voce nella directory specificata
+da \param{newpath} e ad aumentare di uno il numero di riferimenti al file
+(riportato nel campo \var{st\_nlink} della struttura \struct{stat}, vedi
+sez.~\ref{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.
-Per quanto dicevamo in \secref{sec:file_filesystem} la creazione di un
-collegamento diretto è possibile solo se entrambi i pathname sono nello stesso
-filesystem; inoltre il filesystem deve supportare i collegamenti diretti (il
-meccanismo non è disponibile ad esempio con il filesystem \acr{vfat} di
-Windows).
+Per quanto dicevamo in sez.~\ref{sec:file_filesystem} la creazione di un
+collegamento diretto è possibile solo se entrambi i
+\index{\textit{pathname}}\textit{pathname} sono nello stesso filesystem;
+inoltre il filesystem deve supportare i collegamenti diretti (il meccanismo
+non è disponibile ad esempio con il filesystem \acr{vfat} di Windows).
La funzione inoltre opera sia sui file ordinari che sugli altri oggetti del
filesystem, con l'eccezione delle directory. In alcune versioni di Unix solo
l'amministratore è in grado di creare un collegamento diretto ad un'altra
directory: questo viene fatto perché con una tale operazione è possibile
-creare dei circoli nel filesystem (vedi l'esempio mostrato in
-\secref{sec:file_symlink}, dove riprenderemo il discorso) che molti programmi
+creare dei \textit{loop} nel filesystem (vedi l'esempio mostrato in
+sez.~\ref{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
programma \cmd{fsck} per riparare il filesystem).
simbolici che possono fornire la stessa funzionalità senza questi problemi,
nei filesystem usati in Linux questa caratteristica è stata completamente
disabilitata, e al tentativo di creare un link diretto ad una directory la
-funzione restituisce l'errore \macro{EPERM}.
+funzione restituisce l'errore \errcode{EPERM}.
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
+all'interno di una directory) si effettua con la funzione \funcd{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. Nel caso di link
- simbolico cancella il link simbolico; nel caso di socket, fifo o 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[\macro{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 \macro{EPERM} in caso l'operazione non sia
- consentita o il processo non abbia privilegi sufficienti).
- \item[\macro{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[\macro{EISDIR}] \var{pathname} fa riferimento a una directory.
+ \item[\errcode{EISDIR}] \param{pathname} fa riferimento a una directory.
\end{errlist}
- ed inoltre: \macro{EACCES}, \macro{EFAULT}, \macro{ENOENT}, \macro{ENOTDIR},
- \macro{ENOMEM}, \macro{EROFS}, \macro{ELOOP}, \macro{EIO}.}
+ 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 sez.~\ref{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 da \param{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).
-
-Una delle caratteristiche di queste funzioni è che la creazione/rimozione
-del nome dalla directory e l'incremento/decremento del numero di riferimenti
-nell'inode devono essere effettuati in maniera atomica (si veda
-\secref{sec:proc_atom_oper}) senza possibili interruzioni fra le due
+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
+sez.~\ref{sec:file_access_control}). Se inoltre lo \textit{sticky} bit (vedi
+sez.~\ref{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
+nell'inode\index{inode} devono essere effettuati in maniera atomica (si veda
+sez.~\ref{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
+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 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
+ cap.~\ref{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
aprire il file e chiamare \func{unlink} subito dopo, in questo modo il
contenuto del file è sempre disponibile all'interno del processo attraverso il
-suo file descriptor (vedi \secref{sec:file_fd}) fintanto che il processo non
+suo file descriptor (vedi sez.~\ref{sec:file_fd}) fintanto che il processo non
chiude il file, ma non ne resta traccia in nessuna directory, e lo spazio
occupato su disco viene immediatamente rilasciato alla conclusione del
processo (quando tutti i file vengono chiusi).
\subsection{Le funzioni \func{remove} e \func{rename}}
\label{sec:file_remove}
-Al contrario di quanto avviene con altri unix in Linux non è possibile usare
+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{rmdir} (vedi sez.~\ref{sec:file_dir_creat_rem}), oppure la
+funzione \funcd{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 è:
+nello stesso filesystem) si usa invece la funzione \funcd{rename},\footnote{la
+ 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[\macro{EISDIR}] \var{newpath} è una directory mentre \var{oldpath} non
- è una directory.
- \item[\macro{EXDEV}] \var{oldpath} e \var{newpath} non sono sullo stesso
- filesystem.
- \item[\macro{ENOTEMPTY}] \var{newpath} è una directory già esistente e non
- vuota.
- \item[\macro{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[\macro{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[\macro{ENOTDIR}] Uno dei componenti dei pathname non è una directory o
- \var{oldpath} è una directory e \var{newpath} esiste e non è una
+ \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
+ sotto-directory di se stessa.
+ \item[\errcode{ENOTDIR}] Uno dei componenti dei
+ \index{\textit{pathname}}\textit{pathname} non è una directory o
+ \param{oldpath} è una directory e \param{newpath} esiste e non è una
directory.
\end{errlist}
- ed inoltre \macro{EACCESS}, \macro{EPERM}, \macro{EMLINK}, \macro{ENOENT},
- \macro{ENOMEM}, \macro{EROFS}, \macro{ELOOP} e \macro{ENOSPC}.}
+ ed inoltre \errval{EACCES}, \errval{EPERM}, \errval{EMLINK},
+ \errval{ENOENT}, \errval{ENOMEM}, \errval{EROFS}, \errval{ELOOP} e
+ \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
-\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
-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
-\macro{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}.
+\errcode{EISDIR}). Nel caso \param{newpath} indichi un file esistente questo
+viene cancellato e rimpiazzato (atomicamente).
+
+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 \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.
\subsection{I link simbolici}
\label{sec:file_symlink}
-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.
+Come abbiamo visto in sez.~\ref{sec:file_link} la funzione \func{link} crea
+riferimenti agli inode\index{inode}, pertanto può funzionare soltanto per file
+che 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.
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
-al kernel (analogamente a quanto avviene per le directory) per cui per alcune
-funzioni di libreria (come \func{open} o \func{stat}) dare come parametro un
-link simbolico comporta l'applicazione della funzione al file da esso
-specificato. La funzione che permette di creare un nuovo link simbolico è
-\func{symlink}; il suo prototipo è:
+Il sistema funziona in quanto i link simbolici sono riconosciuti come tali dal
+kernel\footnote{è uno dei diversi tipi di file visti in
+ tab.~\ref{tab:file_file_types}, contrassegnato come tale nell'inode, e
+ riconoscibile dal valore del campo \var{st\_mode} della struttura
+ \struct{stat} (vedi sez.~\ref{sec:file_stat}).} per cui alcune funzioni di
+libreria (come \func{open} o \func{stat}) quando ricevono come argomento un
+link simbolico vengono automaticamente applicate al file da esso specificato.
+La funzione che permette di creare un nuovo link simbolico è \funcd{symlink},
+ed il suo prototipo è:
\begin{prototype}{unistd.h}
{int symlink(const char *oldpath, const char *newpath)}
Crea un nuovo link simbolico di nome \param{newpath} il cui contenuto è
\bodydesc{La funzione restituisce zero in caso di successo e -1 per un
errore, nel qual caso la variabile \var{errno} assumerà i valori:
\begin{errlist}
- \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
+ \item[\errcode{EPERM}] il filesystem che contiene \param{newpath} non
+ supporta i link simbolici.
+ \item[\errcode{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
+ \item[\errcode{EEXIST}] esiste già un file \param{newpath}.
+ \item[\errcode{EROFS}] \param{newpath} è su un filesystem montato in sola
lettura.
\end{errlist}
- ed inoltre \macro{EFAULT}, \macro{EACCES}, \macro{ENAMETOOLONG},
- \macro{ENOTDIR}, \macro{ENOMEM}, \macro{ELOOP}, \macro{ENOSPC} e
- \macro{EIO}.}
+ ed inoltre \errval{EFAULT}, \errval{EACCES}, \errval{ENAMETOOLONG},
+ \errval{ENOTDIR}, \errval{ENOMEM}, \errval{ELOOP}, \errval{ENOSPC} e
+ \errval{EIO}.}
\end{prototype}
Si tenga presente che la funzione non effettua nessun controllo sull'esistenza
\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 \tabref{tab:file_symb_effect} si è
-riportato un elenco dei comportamenti delle varie funzioni di libreria che
+all'invocazione delle varie system call; in tab.~\ref{tab:file_symb_effect} si
+è riportato un elenco dei comportamenti delle varie funzioni di libreria che
operano sui file nei confronti della risoluzione dei link simbolici,
specificando quali seguono il link simbolico e quali invece possono operare
direttamente sul suo contenuto.
\textbf{Funzione} & \textbf{Segue il link} & \textbf{Non segue il link} \\
\hline
\hline
- \func{access} & $\bullet$ & \\
- \func{chdir} & $\bullet$ & \\
- \func{chmod} & $\bullet$ & \\
- \func{chown} & & $\bullet$ \\
- \func{creat} & $\bullet$ & \\
- \func{exec} & $\bullet$ & \\
+ \func{access} & $\bullet$ & -- \\
+ \func{chdir} & $\bullet$ & -- \\
+ \func{chmod} & $\bullet$ & -- \\
+ \func{chown} & -- & $\bullet$ \\
+ \func{creat} & $\bullet$ & -- \\
+ \func{exec} & $\bullet$ & -- \\
\func{lchown} & $\bullet$ & $\bullet$ \\
- \func{link} & & \\
- \func{lstat} & & $\bullet$ \\
- \func{mkdir} & $\bullet$ & \\
- \func{mkfifo} & $\bullet$ & \\
- \func{mknod} & $\bullet$ & \\
- \func{open} & $\bullet$ & \\
- \func{opendir} & $\bullet$ & \\
- \func{pathconf} & $\bullet$ & \\
- \func{readlink} & & $\bullet$ \\
- \func{remove} & & $\bullet$ \\
- \func{rename} & & $\bullet$ \\
- \func{stat} & $\bullet$ & \\
- \func{truncate} & $\bullet$ & \\
- \func{unlink} & & $\bullet$ \\
+ \func{link} & -- & -- \\
+ \func{lstat} & -- & $\bullet$ \\
+ \func{mkdir} & $\bullet$ & -- \\
+ \func{mkfifo} & $\bullet$ & -- \\
+ \func{mknod} & $\bullet$ & -- \\
+ \func{open} & $\bullet$ & -- \\
+ \func{opendir} & $\bullet$ & -- \\
+ \func{pathconf} & $\bullet$ & -- \\
+ \func{readlink} & -- & $\bullet$ \\
+ \func{remove} & -- & $\bullet$ \\
+ \func{rename} & -- & $\bullet$ \\
+ \func{stat} & $\bullet$ & -- \\
+ \func{truncate} & $\bullet$ & -- \\
+ \func{unlink} & -- & $\bullet$ \\
\hline
\end{tabular}
\caption{Uso dei link simbolici da parte di alcune funzioni.}
Si noti che non si è specificato il comportamento delle funzioni che operano
con i file descriptor, in quanto la risoluzione del link simbolico viene in
genere effettuata dalla funzione che restituisce il file descriptor
-(normalmente la \func{open}) e tutte le operazioni seguenti fanno riferimento
-solo a quest'ultimo.
+(normalmente la \func{open}, vedi sez.~\ref{sec:file_open}) e tutte le
+operazioni seguenti fanno riferimento solo a quest'ultimo.
-Dato che, come indicato in \tabref{tab:file_symb_effect}, funzioni come la
+Dato che, come indicato in tab.~\ref{tab:file_symb_effect}, funzioni come la
\func{open} seguono i link simbolici, occorrono funzioni apposite per accedere
alle informazioni del link invece che a quelle del file a cui esso fa
riferimento. Quando si vuole leggere il contenuto di un link simbolico si usa
-la funzione \func{readlink}, il cui prototipo è:
+la funzione \funcd{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[\macro{EINVAL}] \param{path} non è un link simbolico o \param{size}
+ \item[\errcode{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
- \macro{ENOMEM}.}
+ ed inoltre \errval{ENOTDIR}, \errval{ENAMETOOLONG}, \errval{ENOENT},
+ \errval{EACCES}, \errval{ELOOP}, \errval{EIO}, \errval{EFAULT} e
+ \errval{ENOMEM}.}
\end{prototype}
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]
\centering
- \includegraphics[width=7cm]{img/link_loop}
+ \includegraphics[width=9cm]{img/link_loop}
\caption{Esempio di loop nel filesystem creato con un link simbolico.}
\label{fig:file_link_loop}
\end{figure}
Un caso comune che si può avere con i link simbolici è la creazione dei
cosiddetti \textit{loop}. La situazione è illustrata in
-\figref{fig:file_link_loop}, che riporta la struttura della directory
+fig.~\ref{fig:file_link_loop}, che riporta 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 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).}
+punta di nuovo a \file{/boot}.\footnote{il loop mostrato in
+ fig.~\ref{fig:file_link_loop} è un usato per poter permettere a \cmd{grub}
+ (un bootloader in grado di leggere direttamente da vari filesystem il file
+ da lanciare come sistema operativo) di vedere i file contenuti nella
+ directory \file{/boot} con lo stesso \textit{pathname} con cui verrebbero
+ visti dal sistema operativo, anche se essi si trovano, come accade spesso,
+ su una partizione separata (che \cmd{grub}, all'avvio, vede 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
\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
-questo limite venga superato viene generato un errore ed \var{errno} viene
-impostata al valore \macro{ELOOP}.
+un \index{\textit{pathname}}\textit{pathname} possano essere seguiti un numero
+limitato di link simbolici, il cui valore limite è specificato dalla costante
+\const{MAXSYMLINKS}. Qualora questo limite venga superato viene generato un
+errore ed \var{errno} viene impostata al valore \errcode{ELOOP}.
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
\subsection{La creazione e la cancellazione delle directory}
\label{sec:file_dir_creat_rem}
-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)}
- 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.
+Benché in sostanza le directory non siano altro che dei file contenenti
+elenchi di nomi ed inode, non è possibile trattarle come file ordinari e
+devono essere create direttamente dal kernel attraverso una opportuna system
+call.\footnote{questo permette anche, attraverso l'uso del VFS, l'utilizzo di
+ diversi formati per la gestione dei suddetti elenchi.} La funzione usata
+per creare una directory è \funcd{mkdir}, ed il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/stat.h}
+ \headdecl{sys/types.h}
+ \funcdecl{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:
\begin{errlist}
- \item[\macro{EEXIST}] Un file (o una directory) con quel nome esiste di già.
- \item[\macro{EACCESS}]
+ \item[\errcode{EEXIST}] Un file (o una directory) con quel nome esiste di
+ già.
+ \item[\errcode{EACCES}]
Non c'è il permesso di scrittura per la directory in cui si vuole inserire
la nuova directory.
- \item[\macro{EMLINK}] La directory in cui si vuole creare la nuova directory
- contiene troppi file. Sotto Linux questo normalmente non avviene perché il
- filesystem standard consente la creazione di un numero di file maggiore di
- quelli che possono essere contenuti nel disco, ma potendo avere a che
- fare anche con filesystem di altri sistemi questo errore può presentarsi.
- \item[\macro{ENOSPC}] Non c'è abbastanza spazio sul file system per creare
+ \item[\errcode{EMLINK}] La directory in cui si vuole creare la nuova
+ directory contiene troppi file. Sotto Linux questo normalmente non avviene
+ perché il filesystem standard consente la creazione di un numero di file
+ maggiore di quelli che possono essere contenuti nel disco, ma potendo
+ avere a che fare anche con filesystem di altri sistemi questo errore può
+ presentarsi.
+ \item[\errcode{ENOSPC}] Non c'è abbastanza spazio sul file system per creare
la nuova directory o si è esaurita la quota disco dell'utente.
\end{errlist}
- ed inoltre anche \macro{EPERM}, \macro{EFAULT}, \macro{ENAMETOOLONG},
- \macro{ENOENT}, \macro{ENOTDIR}, \macro{ENOMEM}, \macro{ELOOP},
- \macro{EROFS}.}
-\end{prototype}
+ ed inoltre anche \errval{EPERM}, \errval{EFAULT}, \errval{ENAMETOOLONG},
+ \errval{ENOENT}, \errval{ENOTDIR}, \errval{ENOMEM}, \errval{ELOOP},
+ \errval{EROFS}.}
+\end{functions}
-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
-\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 è:
+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
+\index{\textit{pathname}}\textit{pathname} assoluto che relativo.
+
+I permessi di accesso alla directory (vedi sez.~\ref{sec:file_access_control})
+sono specificati da \param{mode}, i cui possibili valori sono riportati in
+tab.~\ref{tab:file_permission_const}; questi sono modificati dalla maschera di
+creazione dei file (si veda sez.~\ref{sec:file_umask}). La titolarità della
+nuova directory è impostata secondo quanto riportato in
+sez.~\ref{sec:file_ownership}.
+
+La funzione per la cancellazione di una directory è \funcd{rmdir}, 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[\macro{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
+ \item[\errcode{EPERM}] Il filesystem non supporta la cancellazione di
+ directory, oppure la directory che contiene \param{dirname} ha lo sticky
+ bit impostato e l'user-ID effettivo 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
+ \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
+ \param{dirname}.
+ \item[\errcode{EBUSY}] La directory specificata è la directory di lavoro o la
radice di qualche processo.
- \item[\macro{ENOTEMPTY}] La directory non è vuota.
+ \item[\errcode{ENOTEMPTY}] La directory non è vuota.
\end{errlist}
- ed inoltre anche \macro{EFAULT}, \macro{ENAMETOOLONG}, \macro{ENOENT},
- \macro{ENOTDIR}, \macro{ENOMEM}, \macro{ELOOP}, \macro{EROFS}.}
+ ed inoltre anche \errval{EFAULT}, \errval{ENAMETOOLONG}, \errval{ENOENT},
+ \errval{ENOTDIR}, \errval{ENOMEM}, \errval{ELOOP}, \errval{EROFS}.}
\end{prototype}
+La funzione cancella la directory \param{dirname}, che deve essere vuota (la
+directory deve cioè contenere soltanto le due voci standard \file{.} e
+\file{..}). Il nome può essere indicato con il
+\index{\textit{pathname}}\textit{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 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{..}, a questo punto il kernel non consentirà di creare più
-nuovi file nella directory.
+\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
+occupato su disco non viene rilasciato. Se un processo ha la directory aperta
+la funzione rimuove il link all'inode\index{inode} e nel caso sia l'ultimo,
+pure le voci standard \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 prevede pure
-degli altri tipi di file speciali, come i file di dispositivo e le fifo (i
-socket sono un caso a parte, che vedremo in \capref{cha:socket_intro}).
+sez.~\ref{sec:file_file_types} abbiamo visto però che il sistema prevede pure
+degli altri tipi di file speciali, come i file di dispositivo
+\index{file!di~dispositivo} e le fifo (i socket\index{socket} sono un caso a
+parte, che vedremo in cap.~\ref{cha:socket_intro}).
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:
\begin{errlist}
- \item[\macro{EPERM}] Non si hanno privilegi sufficienti a creare l'inode, o
+ \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[\macro{EINVAL}] Il valore di \var{mode} non indica un file, una fifo o
- un dipositivo.
- \item[\macro{EEXIST}] \param{pathname} esiste già o è un link simbolico.
+ \item[\errcode{EINVAL}] Il valore di \param{mode} non indica un file, una
+ fifo o un dispositivo.
+ \item[\errcode{EEXIST}] \param{pathname} esiste già o è un link simbolico.
\end{errlist}
- ed inoltre anche \macro{EFAULT}, \macro{EACCESS}, \macro{ENAMETOOLONG},
- \macro{ENOENT}, \macro{ENOTDIR}, \macro{ENOMEM}, \macro{ELOOP},
- \macro{ENOSPC}, \macro{EROFS}.}
+ ed inoltre anche \errval{EFAULT}, \errval{EACCES}, \errval{ENAMETOOLONG},
+ \errval{ENOENT}, \errval{ENOTDIR}, \errval{ENOMEM}, \errval{ELOOP},
+ \errval{ENOSPC}, \errval{EROFS}.}
\end{functions}
La funzione permette di creare un file speciale, ma si può usare anche per
creare file regolari 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 combinati con un OR binario. I
+tab.~\ref{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}).
+\var{umask} (si veda sez.~\ref{sec:file_umask}).
-Per il tipo di file può essere specificato solo uno fra: \macro{S\_IFREG} per
-un file regolare (che sarà creato vuoto), \macro{S\_IFBLK} per un device a
-blocchi, \macro{S\_IFCHR} per un device a caratteri e \macro{S\_IFIFO} per una
-fifo. Un valore diverso comporterà l'errore \macro{EINVAL}. Qualora si sia
+Per il tipo di file può essere specificato solo uno fra: \const{S\_IFREG} per
+un file regolare (che sarà creato vuoto), \const{S\_IFBLK} per un device a
+blocchi, \const{S\_IFCHR} per un device a caratteri e \const{S\_IFIFO} per una
+fifo. Un valore diverso comporterà l'errore \errcode{EINVAL}. Qualora si sia
specificato in \param{mode} un file di dispositivo, il valore di \param{dev}
viene usato per indicare a quale dispositivo si fa riferimento.
codici di errore.} l'uso per la creazione di una fifo è consentito anche
agli utenti normali.
-I nuovi inode creati con \func{mknod} apparterranno al proprietario e al
-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.
+I nuovi inode\index{inode} creati con \func{mknod} apparterranno al
+proprietario e al 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 sez.~\ref{sec:file_ownership}) in cui si va a
+creare l'inode\index{inode}.
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 è:
+sez.~\ref{sec:ipc_named_pipe}) lo standard POSIX specifica l'uso della funzione
+\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 \macro{EACCESS},
- \macro{EEXIST}, \macro{ENAMETOOLONG}, \macro{ENOENT}, \macro{ENOSPC},
- \macro{ENOTDIR} e \macro{EROFS}.}
+ errore, nel qual caso \var{errno} assumerà i valori \errval{EACCES},
+ \errval{EEXIST}, \errval{ENAMETOOLONG}, \errval{ENOENT}, \errval{ENOSPC},
+ \errval{ENOTDIR} e \errval{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
-\param{mode} vengono modificati dal valore di \var{umask}.
+
+La funzione crea la fifo \param{pathname} con i permessi \param{mode}. Come
+per \func{mknod} il file \param{pathname} non deve esistere (neanche come link
+simbolico); al solito i permessi specificati da \param{mode} vengono
+modificati dal valore di \var{umask}.
\subsection{Accesso alle directory}
\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
-processi devono creare i file usando le apposite funzioni.
+Benché le directory alla fine non siano altro che dei file che contengono
+delle liste di nomi ed inode, per il ruolo che rivestono nella struttura del
+sistema, non possono essere trattate come dei normali file di dati. Ad
+esempio, onde evitare inconsistenze all'interno del filesystem, solo il kernel
+può scrivere il contenuto di una directory, e non può essere un processo a
+inserirvi direttamente delle voci con le usuali funzioni di scrittura.
+
+Ma se la scrittura e l'aggiornamento dei dati delle directory è compito del
+kernel, sono molte le situazioni in cui i processi necessitano di poterne
+leggere il contenuto. Benché questo possa essere fatto direttamente (vedremo
+in sez.~\ref{sec:file_open} che è possibile aprire una directory come se fosse
+un file, anche se solo in sola lettura) in generale il formato con cui esse
+sono scritte può dipendere dal tipo di filesystem, tanto che, come riportato
+in tab.~\ref{tab:file_file_operations}, il VFS del kernel prevede una apposita
+funzione per la lettura delle directory.
+
+Tutto questo si riflette nello standard POSIX\footnote{le funzioni sono
+ previste pure in BSD e SVID.} che ha introdotto una apposita interfaccia per
+la lettura delle directory, basata sui cosiddetti \textit{directory stream}
+(chiamati così per l'analogia con i file stream dell'interfaccia standard di
+cap.~\ref{cha:files_std_interface}). La prima funzione di questa interfaccia è
+\funcd{opendir}, il cui prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h} \headdecl{dirent.h}
+
+ \funcdecl{DIR * opendir(const char *dirname)}
+
+ 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
+\param{dirname}, ritornando il puntatore ad un oggetto di tipo \type{DIR} (che
+è il tipo opaco\index{tipo!opaco} usato dalle librerie per gestire i
+\textit{directory stream}) da usare per tutte le operazioni successive, la
+funzione inoltre posiziona lo stream sulla prima voce contenuta nella
+directory.
+
+Dato che le directory sono comunque dei file, in alcuni casi può servire
+conoscere il \textit{file descriptor} associato ad un \textit{directory
+ stream}, 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}
-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}.
+La funzione\footnote{questa funzione è una estensione di BSD non presente in
+ POSIX, 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}. Di
+solito si utilizza questa funzione in abbinamento alla funzione \func{fchdir}
+per cambiare la directory di lavoro (vedi sez.~\ref{sec:file_work_dir}) a
+quella relativa allo stream che si sta esaminando.
+
+La lettura di una voce della directory viene effettuata attraverso la funzione
+\funcd{readdir}; il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h} \headdecl{dirent.h}
+
+ \funcdecl{struct dirent *readdir(DIR *dir)}
+
+ Legge una voce dal \textit{directory stream}.
+
+ \bodydesc{La funzione restituisce il puntatore alla struttura contenente i
+ dati in caso di successo e \val{NULL} altrimenti, in caso di descrittore
+ non valido \var{errno} assumerà il valore \errval{EBADF}, il valore
+ \val{NULL} viene restituito anche quando si raggiunge la fine dello
+ stream.}
+\end{functions}
-(NdA Il resto va scritto!!! É noioso e lo farò più avanti).
+La funzione legge la voce corrente nella directory, posizionandosi sulla voce
+successiva. I dati vengono memorizzati in una struttura \struct{dirent} (la
+cui definizione\footnote{la definizione è quella usata a Linux, che si trova
+ nel file \file{/usr/include/bits/dirent.h}, essa non contempla la presenza
+ del campo \var{d\_namlen} che indica la lunghezza del nome del file (ed
+ infatti la macro \macro{\_DIRENT\_HAVE\_D\_NAMLEN} non è definita).} è
+riportata in fig.~\ref{fig:file_dirent_struct}). La funzione restituisce il
+puntatore alla struttura; si tenga presente però che quest'ultima è allocata
+staticamente, per cui viene sovrascritta tutte le volte che si ripete la
+lettura di una voce sullo stesso stream.
+
+Di questa funzione esiste anche una versione rientrante, \func{readdir\_r},
+che non usa una struttura allocata staticamente, e può essere utilizzata anche
+con i thread; il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h} \headdecl{dirent.h}
+
+ \funcdecl{int readdir\_r(DIR *dir, struct dirent *entry,
+ struct dirent **result)}
+
+ Legge una voce dal \textit{directory stream}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore, gli errori sono gli stessi di \func{readdir}.}
+\end{functions}
+
+La funzione restituisce in \param{result} (come
+\index{\textit{value~result~argument}}\textit{value result argument})
+l'indirizzo dove sono stati salvati i dati, che di norma corrisponde a quello
+della struttura precedentemente allocata e specificata dall'argomento
+\param{entry} (anche se non è assicurato che la funzione usi lo spazio fornito
+dall'utente).
+
+I vari campi di \struct{dirent} contengono le informazioni relative alle voci
+presenti nella directory; sia BSD che SVr4\footnote{POSIX prevede invece solo
+ la presenza del campo \var{d\_fileno}, identico \var{d\_ino}, che in Linux è
+ definito come alias di quest'ultimo. Il campo \var{d\_name} è considerato
+ dipendente dall'implementazione.} prevedono che siano sempre presenti il
+campo \var{d\_name}, che contiene il nome del file nella forma di una stringa
+terminata da uno zero,\footnote{lo standard POSIX non specifica una lunghezza,
+ ma solo un limite \const{NAME\_MAX}; in SVr4 la lunghezza del campo è
+ definita come \code{NAME\_MAX+1} che di norma porta al valore di 256 byte
+ usato anche in Linux.} ed il campo \var{d\_ino}, che contiene il numero di
+inode cui il file è associato (di solito corrisponde al campo \var{st\_ino} di
+\struct{stat}).
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includestruct{listati/dirent.c}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \structd{dirent} per la lettura delle informazioni dei
+ file.}
+ \label{fig:file_dirent_struct}
+\end{figure}
+
+La presenza di ulteriori campi opzionali è segnalata dalla definizione di
+altrettante macro nella forma \code{\_DIRENT\_HAVE\_D\_XXX} dove \code{XXX} è
+il nome del relativo campo; nel nostro caso sono definite le macro
+\macro{\_DIRENT\_HAVE\_D\_TYPE}, \macro{\_DIRENT\_HAVE\_D\_OFF} e
+\macro{\_DIRENT\_HAVE\_D\_RECLEN}.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|l|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{DT\_UNKNOWN} & tipo sconosciuto. \\
+ \const{DT\_REG} & file normale. \\
+ \const{DT\_DIR} & directory. \\
+ \const{DT\_FIFO} & fifo. \\
+ \const{DT\_SOCK} & socket. \\
+ \const{DT\_CHR} & dispositivo a caratteri. \\
+ \const{DT\_BLK} & dispositivo a blocchi. \\
+ \hline
+ \end{tabular}
+ \caption{Costanti che indicano i vari tipi di file nel campo \var{d\_type}
+ della struttura \struct{dirent}.}
+ \label{tab:file_dtype_macro}
+\end{table}
+
+Per quanto riguarda il significato dei campi opzionali, il campo \var{d\_type}
+indica il tipo di file (fifo, directory, link simbolico, ecc.); i suoi
+possibili valori\footnote{fino alla versione 2.1 delle \acr{glibc} questo
+ campo, pur presente nella struttura, non è implementato, e resta sempre al
+ valore \const{DT\_UNKNOWN}.} sono riportati in
+tab.~\ref{tab:file_dtype_macro}; per la conversione da e verso l'analogo valore
+mantenuto dentro il campo \var{st\_mode} di \struct{stat} sono definite anche
+due macro di conversione \macro{IFTODT} e \macro{DTTOIF}:
+\begin{functions}
+ \funcdecl{int IFTODT(mode\_t MODE)} Converte il tipo di file dal formato di
+ \var{st\_mode} a quello di \var{d\_type}.
+
+ \funcdecl{mode\_t DTTOIF(int DTYPE)} Converte il tipo di file dal formato di
+ \var{d\_type} a quello di \var{st\_mode}.
+\end{functions}
+
+Il campo \var{d\_off} contiene invece la posizione della voce successiva della
+directory, mentre il campo \var{d\_reclen} la lunghezza totale della voce
+letta. Con questi due campi diventa possibile, determinando la posizione delle
+varie voci, spostarsi all'interno dello stream usando la funzione
+\func{seekdir},\footnote{sia questa funzione che \func{telldir}, sono
+ estensioni prese da BSD, non previste dallo standard POSIX.} il cui
+prototipo è:
+\begin{prototype}{dirent.h}{void seekdir(DIR *dir, off\_t offset)}
+ Cambia la posizione all'interno di un \textit{directory stream}.
+\end{prototype}
+
+La funzione non ritorna nulla e non segnala errori, è però necessario che il
+valore dell'argomento \param{offset} sia valido per lo stream \param{dir};
+esso pertanto deve essere stato ottenuto o dal valore di \var{d\_off} di
+\struct{dirent} o dal valore restituito dalla funzione \func{telldir}, che
+legge la posizione corrente; il prototipo di quest'ultima è:
+\begin{prototype}{dirent.h}{off\_t telldir(DIR *dir)}
+ Ritorna la posizione corrente in un \textit{directory stream}.
+
+ \bodydesc{La funzione restituisce la posizione corrente nello stream (un
+ numero positivo) in caso di successo, e -1 altrimenti, nel qual caso
+ \var{errno} assume solo il valore di \errval{EBADF}, corrispondente ad un
+ valore errato per \param{dir}.}
+\end{prototype}
+
+La sola funzione di posizionamento nello stream prevista dallo standard POSIX
+è \funcd{rewinddir}, che riporta la posizione a quella iniziale; il suo
+prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h} \headdecl{dirent.h}
+
+ \funcdecl{void rewinddir(DIR *dir)}
+
+ Si posiziona all'inizio di un \textit{directory stream}.
+\end{functions}
+
+
+Una volta completate le operazioni si può chiudere il \textit{directory
+ stream} con la funzione \funcd{closedir}, il cui prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h} \headdecl{dirent.h}
+
+ \funcdecl{int closedir(DIR * dir)}
+
+ Chiude un \textit{directory stream}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 altrimenti, nel
+ qual caso \var{errno} assume il valore \errval{EBADF}.}
+\end{functions}
+
+A parte queste funzioni di base in BSD 4.3 è stata introdotta un'altra
+funzione che permette di eseguire una scansione completa (con tanto di ricerca
+ed ordinamento) del contenuto di una directory; la funzione è
+\funcd{scandir}\footnote{in Linux questa funzione è stata introdotta fin dalle
+ libc4.} ed il suo prototipo è:
+\begin{prototype}{dirent.h}{int scandir(const char *dir,
+ struct dirent ***namelist, int(*select)(const struct dirent *),
+ int(*compar)(const struct dirent **, const struct dirent **))}
+
+ Esegue una scansione di un \textit{directory stream}.
+
+ \bodydesc{La funzione restituisce in caso di successo il numero di voci
+ trovate, e -1 altrimenti.}
+\end{prototype}
+
+Al solito, per la presenza fra gli argomenti di due puntatori a funzione, il
+prototipo non è molto comprensibile; queste funzioni però sono quelle che
+controllano rispettivamente la selezione di una voce (\param{select}) e
+l'ordinamento di tutte le voci selezionate (\param{compar}).
+
+La funzione legge tutte le voci della directory indicata dall'argomento
+\param{dir}, passando ciascuna di esse come argomento alla funzione di
+\param{select}; se questa ritorna un valore diverso da zero la voce viene
+inserita in una struttura allocata dinamicamente con \func{malloc}, qualora si
+specifichi un valore \val{NULL} per \func{select} vengono selezionate tutte le
+voci. Tutte le voci selezionate vengono poi inserite un una lista (anch'essa
+allocata con \func{malloc}, che viene riordinata tramite \func{qsort} usando
+la funzione \param{compar} come criterio di ordinamento; alla fine l'indirizzo
+della lista ordinata è restituito nell'argomento \param{namelist}.
+
+Per l'ordinamento sono disponibili anche due funzioni predefinite,
+\funcd{alphasort} e \funcd{versionsort}, i cui prototipi sono:
+\begin{functions}
+ \headdecl{dirent.h}
+
+ \funcdecl{int alphasort(const void *a, const void *b)}
+
+ \funcdecl{int versionsort(const void *a, const void *b)}
+
+ Funzioni per l'ordinamento delle voci di \textit{directory stream}.
+
+ \bodydesc{Le funzioni restituiscono un valore minore, uguale o maggiore di
+ zero qualora il primo argomento sia rispettivamente minore, uguale o
+ maggiore del secondo.}
+\end{functions}
+
+La funzione \func{alphasort} deriva da BSD ed è presente in Linux fin dalle
+libc4\footnote{la versione delle libc4 e libc5 usa però come argomenti dei
+ puntatori a delle strutture \struct{dirent}; le glibc usano il prototipo
+ originario di BSD, mostrato anche nella definizione, che prevede puntatori a
+ \ctyp{void}.} e deve essere specificata come argomento \param{compare} per
+ottenere un ordinamento alfabetico (secondo il valore del campo \var{d\_name}
+delle varie voci). Le \acr{glibc} prevedono come estensione\footnote{le glibc,
+ a partire dalla versione 2.1, effettuano anche l'ordinamento alfabetico
+ tenendo conto delle varie localizzazioni, usando \func{strcoll} al posto di
+ \func{strcmp}.} anche \func{versionsort}, che ordina i nomi tenendo conto
+del numero di versione (cioè qualcosa per cui \file{file10} viene comunque
+dopo \func{file4}.)
+
+Un semplice esempio dell'uso di queste funzioni è riportato in
+fig.~\ref{fig:file_my_ls}, dove si è riportata la sezione principale di un
+programma che, usando la routine di scansione illustrata in
+fig.~\ref{fig:file_dirscan}, stampa i nomi dei file contenuti in una directory
+e la relativa dimensione (in sostanza una versione semplificata del comando
+\cmd{ls}).
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15.6cm}
+ \includecodesample{listati/my_ls.c}
+ \end{minipage}
+ \caption{Esempio di codice per eseguire la lista dei file contenuti in una
+ directory.}
+ \label{fig:file_my_ls}
+\end{figure}
+
+Il programma è estremamente semplice; in fig.~\ref{fig:file_my_ls} si è omessa
+la parte di gestione delle opzioni (che prevede solo l'uso di una funzione per
+la stampa della sintassi, anch'essa omessa) ma il codice completo potrà essere
+trovato coi sorgenti allegati nel file \file{myls.c}.
+
+In sostanza tutto quello che fa il programma, dopo aver controllato
+(\texttt{\small 10--13}) di avere almeno un parametro (che indicherà la
+directory da esaminare) è chiamare (\texttt{\small 14}) la funzione
+\func{DirScan} per eseguire la scansione, usando la funzione \code{do\_ls}
+(\texttt{\small 20--26}) per fare tutto il lavoro.
+
+Quest'ultima si limita (\texttt{\small 23}) a chiamare \func{stat} sul file
+indicato dalla directory entry passata come argomento (il cui nome è appunto
+\var{direntry->d\_name}), memorizzando in una opportuna struttura \var{data} i
+dati ad esso relativi, per poi provvedere (\texttt{\small 24}) a stampare il
+nome del file e la dimensione riportata in \var{data}.
+
+Dato che la funzione verrà chiamata all'interno di \func{DirScan} per ogni
+voce presente questo è sufficiente a stampare la lista completa dei file e
+delle relative dimensioni. Si noti infine come si restituisca sempre 0 come
+valore di ritorno per indicare una esecuzione senza errori.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15.6cm}
+ \includecodesample{listati/DirScan.c}
+ \end{minipage}
+ \caption{Codice della routine di scansione di una directory contenuta nel
+ file \file{DirScan.c}.}
+ \label{fig:file_dirscan}
+\end{figure}
+
+Tutto il grosso del lavoro è svolto dalla funzione \func{DirScan}, riportata
+in fig.~\ref{fig:file_dirscan}. La funzione è volutamente generica e permette
+di eseguire una funzione, passata come secondo argomento, su tutte le voci di
+una directory. La funzione inizia con l'aprire (\texttt{\small 19--23}) uno
+stream sulla directory passata come primo argomento, stampando un messaggio in
+caso di errore.
+
+Il passo successivo (\texttt{\small 24--25}) è cambiare directory di lavoro
+(vedi sez.~\ref{sec:file_work_dir}), usando in sequenza le funzione
+\func{dirfd} e \func{fchdir} (in realtà si sarebbe potuto usare direttamente
+\func{chdir} su \var{dirname}), in modo che durante il successivo ciclo
+(\texttt{\small 27--31}) sulle singole voci dello stream ci si trovi
+all'interno della directory.\footnote{questo è essenziale al funzionamento
+ della funzione \code{do\_ls} (e ad ogni funzione che debba usare il campo
+ \var{d\_name}, in quanto i nomi dei file memorizzati all'interno di una
+ struttura \struct{dirent} sono sempre relativi alla directory in questione,
+ e senza questo posizionamento non si sarebbe potuto usare \func{stat} per
+ ottenere le dimensioni.}
+
+Avendo usato lo stratagemma di fare eseguire tutte le manipolazioni necessarie
+alla funzione passata come secondo argomento, il ciclo di scansione della
+directory è molto semplice; si legge una voce alla volta (\texttt{\small 27})
+all'interno di una istruzione di \code{while} e fintanto che si riceve una
+voce valida (cioè un puntatore diverso da \val{NULL}) si esegue
+(\texttt{\small 27}) la funzione di elaborazione \var{compare} (che nel nostro
+caso sarà \code{do\_ls}), ritornando con un codice di errore (\texttt{\small
+ 28}) qualora questa presenti una anomalia (identificata da un codice di
+ritorno negativo).
+
+Una volta terminato il ciclo la funzione si conclude con la chiusura
+(\texttt{\small 32}) dello stream\footnote{nel nostro caso, uscendo subito
+ dopo la chiamata, questo non servirebbe, in generale però l'operazione è
+ necessaria, dato che la funzione può essere invocata molte volte all'interno
+ dello stesso processo, per cui non chiudere gli stream comporterebbe un
+ consumo progressivo di risorse, con conseguente rischio di esaurimento delle
+ stesse} e la restituzione (\texttt{\small 33}) del codice di operazioni
+concluse con successo.
\subsection{La directory di lavoro}
\label{sec:file_work_dir}
-A ciascun processo è associato ad una directory nel filesystem che è chiamata
-directory corrente o directory di lavoro (\textit{current working directory})
-che è quella a cui si fa riferimento quando un filename è espresso in forma
-relativa, dove il ``relativa'' fa riferimento appunto a questa directory.
+A ciascun processo è associata una directory nel filesystem che è chiamata
+\textsl{directory corrente} o \textsl{directory di lavoro} (in inglese
+\textit{current working directory}) che è quella a cui si fa riferimento
+quando un \index{\textit{pathname}}\textit{pathname} è espresso in forma
+relativa, dove il ``\textsl{relativa}'' fa riferimento appunto a questa
+directory.
-Quando un utente effettua il login questa directory viene impostata alla
+Quando un utente effettua il login, questa directory viene impostata alla
\textit{home directory} del suo account. Il comando \cmd{cd} della shell
consente di cambiarla a piacere, spostandosi da una directory ad un'altra, il
comando \cmd{pwd} la stampa sul terminale. Siccome la directory corrente
resta la stessa quando viene creato un processo figlio (vedi
-\secref{sec:proc_fork}), la directory corrente della shell diventa anche la
+sez.~\ref{sec:proc_fork}), la directory corrente della shell diventa anche la
directory corrente di qualunque comando da essa lanciato.
-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 è:
+In genere il kernel tiene traccia per ciascun processo dell'inode\index{inode}
+della directory di lavoro, per ottenere il
+\index{\textit{pathname}}\textit{pathname} occorre usare una apposita funzione
+di libreria, \funcd{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}.
+ Legge il \textit{pathname} della directory di lavoro corrente.
- \bodydesc{La funzione restituisce il puntatore \var{buffer} se riesce,
- \macro{NULL} se fallisce, in quest'ultimo caso la variabile
+ \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[\macro{EINVAL}] L'argomento \var{size} è zero e \var{buffer} non
+ \item[\errcode{EINVAL}] L'argomento \param{size} è zero e \param{buffer} non
è nullo.
- \item[\macro{ERANGE}] L'argomento \var{size} è più piccolo della
- lunghezza del pathname.
- \item[\macro{EACCESS}] Manca il permesso di lettura o di ricerca su uno dei
- componenti del pathname (cioè su una delle directory superiori alla
- corrente).
+ \item[\errcode{ERANGE}] L'argomento \param{size} è più piccolo della
+ lunghezza del \textit{pathname}.
+ \item[\errcode{EACCES}] Manca il permesso di lettura o di ricerca su uno dei
+ componenti del \textit{pathname} (cioè su una delle directory superiori
+ alla corrente).
\end{errlist}}
\end{prototype}
-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 è
- un'estensione allo standard POSIX.1, supportata da Linux.} nel qual caso la
-stringa sarà allocata automaticamente per una dimensione pari a \var{size}
-qualora questa sia diversa da zero, o della lunghezza esatta del pathname
+La funzione restituisce il \index{\textit{pathname}}\textit{pathname} completo
+della directory di lavoro nella stringa puntata da \param{buffer}, che deve
+essere precedentemente allocata, per una dimensione massima di \param{size}.
+Il buffer deve essere sufficientemente lungo da poter contenere il
+\textit{pathname} completo più lo zero di terminazione della stringa. Qualora
+esso ecceda le dimensioni specificate con \param{size} la funzione restituisce
+un errore.
+
+Si può anche specificare un puntatore nullo come
+\param{buffer},\footnote{questa è un'estensione allo standard POSIX.1,
+ supportata da Linux.} nel qual caso la stringa sarà allocata automaticamente
+per una dimensione pari a \param{size} qualora questa sia diversa da zero, o
+della lunghezza esatta del \index{\textit{pathname}}\textit{pathname}
altrimenti. In questo caso ci si deve ricordare di disallocare la stringa una
volta cessato il suo utilizzo.
-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
-\secref{sec:sys_limits}); il problema è che in Linux non esiste una dimensione
-superiore per un pathname, per cui non è detto che il buffer sia sufficiente a
-contenere il nome del file, e questa è la ragione principale per cui questa
-funzione è deprecata.
+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 \const{PATH\_MAX} (di solito 256 byte, vedi
+sez.~\ref{sec:sys_limits}); il problema è che in Linux non esiste una
+dimensione superiore per un \index{\textit{pathname}}\textit{pathname}, per
+cui non è detto che il buffer sia sufficiente a contenere il nome del file, e
+questa è la ragione principale per cui questa funzione è deprecata.
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 un pathname comprendente anche
-dei link simbolici. Usando \func{getcwd} infatti, essendo il pathname ricavato
-risalendo all'indietro l'albero della directory, si perderebbe traccia di ogni
-passaggio attraverso eventuali link simbolici.
-
-Per cambiare la directory di lavoro corrente si può usare la funzione
-\func{chdir} (equivalente del comando di shell \cmd{cd}) il cui nome sta
-appunto per \textit{change directory}, il suo prototipo è:
+differenza che essa ritorna il valore della variabile di ambiente \val{PWD},
+che essendo costruita dalla shell può contenere un \textit{pathname}
+comprendente anche dei link simbolici. Usando \func{getcwd} infatti, essendo
+il \index{\textit{pathname}}\textit{pathname} ricavato risalendo all'indietro
+l'albero della directory, si perderebbe traccia di ogni passaggio attraverso
+eventuali link simbolici.
+
+Per cambiare la directory di lavoro si può usare la funzione \funcd{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}.
+ Cambia la directory di lavoro in \param{pathname}.
\bodydesc{La funzione restituisce 0 in caso di successo e -1 per un errore,
nel qual caso \var{errno} assumerà i valori:
\begin{errlist}
- \item[\macro{ENOTDIR}] Non si è specificata una directory.
- \item[\macro{EACCESS}] Manca il permesso di ricerca su uno dei componenti di
- \param{path}.
+ \item[\errcode{ENOTDIR}] Non si è specificata una directory.
+ \item[\errcode{EACCES}] Manca il permesso di ricerca su uno dei componenti
+ di \param{path}.
\end{errlist}
- ed inoltre \macro{EFAULT}, \macro{ENAMETOOLONG}, \macro{ENOENT},
- \macro{ENOMEM}, \macro{ELOOP} e \macro{EIO}.}
+ ed inoltre \errval{EFAULT}, \errval{ENAMETOOLONG}, \errval{ENOENT},
+ \errval{ENOMEM}, \errval{ELOOP} e \errval{EIO}.}
\end{prototype}
\noindent ed ovviamente \param{pathname} deve indicare una directory per la
quale si hanno i permessi di accesso.
Dato che anche le directory sono file, è possibile riferirsi ad esse anche
-tramite il file descriptor, e non solo tramite il filename, per fare questo si
-usa \func{fchdir}, il cui prototipo è:
+tramite il file descriptor, e non solo tramite il
+\index{\textit{pathname}}\textit{pathname}, per fare questo si usa
+\funcd{fchdir}, il cui prototipo è:
\begin{prototype}{unistd.h}{int fchdir(int fd)}
Identica a \func{chdir}, ma usa il file descriptor \param{fd} invece del
- pathname.
+ \textit{pathname}.
\bodydesc{La funzione restituisce zero in caso di successo e -1 per un
- errore, in caso di errore \var{errno} assumerà i valori \macro{EBADF} o
- \macro{EACCES}.}
+ errore, in caso di errore \var{errno} assumerà i valori \errval{EBADF} o
+ \errval{EACCES}.}
\end{prototype}
\noindent anche in questo caso \param{fd} deve essere un file descriptor
valido che fa riferimento ad una directory. Inoltre l'unico errore di accesso
-possibile (tutti gli altri sarebbero occorsi all'apertura di \func{fd}), è
+possibile (tutti gli altri sarebbero occorsi all'apertura di \param{fd}), è
quello in cui il processo non ha il permesso di accesso alla directory
specificata da \param{fd}.
\label{sec:file_temp_file}
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
+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}).
+controllo e la creazione si ha giusto lo spazio per una possibile \textit{race
+ condition}\index{\textit{race~condition}} (si ricordi quanto visto in
+sez.~\ref{sec:proc_race_cond}).
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 è:
+di queste funzioni è \funcd{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.}
+ \val{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à
+essere di dimensione \const{L\_tmpnam} (costante definita in \file{stdio.h},
+come \const{P\_tmpdir} e \const{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}.
+massimo di \const{TMP\_MAX} volte. Al nome viene automaticamente aggiunto come
+prefisso la directory specificata da \const{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
+fa nulla quando si passa \val{NULL} come parametro. Una funzione simile,
+\funcd{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 impostata a
- \macro{ENOMEM} qualora fallisca l'allocazione della stringa.}
+ \val{NULL} in caso di fallimento, \var{errno} viene impostata a
+ \errval{ENOMEM} qualora fallisca l'allocazione della stringa.}
\end{prototype}
La funzione alloca con \code{malloc} la stringa in cui restituisce il nome,
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 è
+\item La variabile di ambiente \const{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}.
+ sez.~\ref{sec:file_suid_sgid}).
+\item il valore dell'argomento \param{dir} (se diverso da \val{NULL}).
+\item Il valore della costante \const{P\_tmpdir}.
\item la directory \file{/tmp}.
\end{itemize*}
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
+(cioè con l'opzione \const{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 è:
+POSIX definisce la funzione \funcd{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
+ temporaneo in caso di successo e \val{NULL} in caso di errore, nel qual
caso \var{errno} assumerà i valori:
\begin{errlist}
- \item[\macro{EINTR}] La funzione è stata interrotta da un segnale.
- \item[\macro{EEXIST}] Non è stato possibile generare un nome univoco.
+ \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
+ \item[\errcode{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}.}
+ ed inoltre \errval{EFAULT}, \errval{EMFILE}, \errval{ENFILE},
+ \errval{ENOSPC}, \errval{EROFS} e \errval{EACCES}.}
\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
+\code{r+b}, si veda sez.~\ref{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 le
-\acr{glibc} prima tentano con \macro{P\_tmpdir} e poi con \file{/tmp}. Questa
+\acr{glibc} prima tentano con \const{P\_tmpdir} e poi con \file{/tmp}. Questa
funzione è rientrante e non soffre di problemi di \textit{race
- condition}\index{race condition}.
+ condition}\index{\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
+caso si possono usare le vecchie funzioni \funcd{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,
+unico. La prima delle due è analoga a \funcd{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}
+ successo e \val{NULL} in caso di errore, nel qual caso \var{errno}
assumerà i valori:
\begin{errlist}
- \item[\macro{EINVAL}] \param{template} non termina con \code{XXXXXX}.
+ \item[\errcode{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}\index{race condition} date per
+alle possibili \textit{race condition}\index{\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.
-
-
+il valore 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
+La seconda funzione, \funcd{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)}
\bodydesc{La funzione ritorna il file descriptor in caso successo e
-1 in caso di errore, nel qual caso \var{errno} assumerà i valori:
\begin{errlist}
- \item[\macro{EINVAL}] \param{template} non termina con \code{XXXXXX}.
- \item[\macro{EEXIST}] non è riuscita a creare un file temporano, il
+ \item[\errcode{EINVAL}] \param{template} non termina con \code{XXXXXX}.
+ \item[\errcode{EEXIST}] non è riuscita a creare un file temporaneo, 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
+la funzione \func{open}, usando l'opzione \const{O\_EXCL} (si veda
+sez.~\ref{sec:file_open}), in questo modo al ritorno della funzione si ha la
certezza di essere i soli utenti del file. I permessi sono impostati 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}).
+ contenuti del file.} (si veda sez.~\ref{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 è:
+\funcd{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}
+ successo e \val{NULL} in caso di errore, nel qual caso \var{errno}
assumerà i valori:
\begin{errlist}
- \item[\macro{EINVAL}] \param{template} non termina con \code{XXXXXX}.
+ \item[\errcode{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}\index{race condition} non si pongono.
+cap.~\ref{cha:file_unix_interface} per i dettagli); dato che la creazione
+della directory è sempre esclusiva i precedenti problemi di \textit{race
+ condition}\index{\textit{race~condition}} non si pongono.
\section{La manipolazione delle caratteristiche dei files}
\label{sec:file_infos}
-Come spiegato in \secref{sec:file_filesystem} tutte le informazioni
-generali relative alle caratteristiche di ciascun file, a partire dalle
-informazioni relative al controllo di accesso, sono mantenute nell'inode.
+Come spiegato in sez.~\ref{sec:file_filesystem} tutte le informazioni generali
+relative alle caratteristiche di ciascun file, a partire dalle informazioni
+relative al controllo di accesso, sono mantenute nell'inode\index{inode}.
Vedremo in questa sezione come sia possibile leggere tutte queste informazioni
usando la funzione \func{stat}, che permette l'accesso a tutti i dati
-memorizzati nell'inode; esamineremo poi le varie funzioni usate per manipolare
-tutte queste informazioni (eccetto quelle che riguardano la gestione del
-controllo di accesso, trattate in in \secref{sec:file_access_control}).
+memorizzati nell'inode\index{inode}; esamineremo poi le varie funzioni usate
+per manipolare tutte queste informazioni (eccetto quelle che riguardano la
+gestione del controllo di accesso, trattate in in
+sez.~\ref{sec:file_access_control}).
\subsection{Le funzioni \func{stat}, \func{fstat} e \func{lstat}}
\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
- lette le informazioni relativa ad esso e non al file a cui fa riferimento.
+ \func{stat} eccetto che se il \param{file\_name} è un link simbolico vengono
+ lette le informazioni relativae 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: \macro{EBADF},
- \macro{ENOENT}, \macro{ENOTDIR}, \macro{ELOOP}, \macro{EFAULT},
- \macro{EACCESS}, \macro{ENOMEM}, \macro{ENAMETOOLONG}.}
+ errore, nel qual caso \var{errno} assumerà uno dei valori: \errval{EBADF},
+ \errval{ENOENT}, \errval{ENOTDIR}, \errval{ELOOP}, \errval{EFAULT},
+ \errval{EACCES}, \errval{ENOMEM}, \errval{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} 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
+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 fig.~\ref{fig:file_stat_struct}, così come
riportata dalla pagina di manuale 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).
\footnotesize
\centering
\begin{minipage}[c]{15cm}
- \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-struct stat {
- dev_t st_dev; /* device */
- ino_t st_ino; /* inode */
- mode_t st_mode; /* protection */
- nlink_t st_nlink; /* number of hard links */
- uid_t st_uid; /* user ID of owner */
- gid_t st_gid; /* group ID of owner */
- dev_t st_rdev; /* device type (if inode device) */
- off_t st_size; /* total size, in bytes */
- unsigned long st_blksize; /* blocksize for filesystem I/O */
- unsigned long st_blocks; /* number of blocks allocated */
- time_t st_atime; /* time of last access */
- time_t st_mtime; /* time of last modification */
- time_t st_ctime; /* time of last change */
-};
- \end{lstlisting}
+ \includestruct{listati/stat.h}
\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}
-Si noti come i vari membri della struttura siano specificati come tipi nativi
-del sistema (di quelli definiti in \tabref{tab:xxx_sys_types}, e dichiarati in
-\file{sys/types.h}).
+Si noti come i vari membri della struttura siano specificati come tipi
+primitivi del sistema (di quelli definiti in
+tab.~\ref{tab:intro_primitive_types}, e dichiarati in \file{sys/types.h}).
\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} come maschera binaria nel campo
-\var{st\_mode} (che che contiene anche le informazioni relative ai permessi).
+Come riportato in tab.~\ref{tab:file_file_types} in Linux oltre ai file e alle
+directory esistono 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 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,
+standard POSIX definisce un insieme di macro per verificare il tipo di file,
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 \tabref{tab:file_type_macro}.
+standard per i link simbolici e i socket\index{socket} definite da BSD;
+l'elenco completo delle macro con cui è possibile estrarre l'informazione da
+\var{st\_mode} è riportato in tab.~\ref{tab:file_type_macro}.
\begin{table}[htb]
\centering
\footnotesize
\hline
\macro{S\_ISREG(m)} & file regolare \\
\macro{S\_ISDIR(m)} & directory \\
- \macro{S\_ISCHR(m)} & device a caratteri \\
- \macro{S\_ISBLK(m)} & device a blocchi\\
+ \macro{S\_ISCHR(m)} & dispositivo a caratteri \\
+ \macro{S\_ISBLK(m)} & dispositivo a blocchi\\
\macro{S\_ISFIFO(m)} & fifo \\
\macro{S\_ISLNK(m)} & link simbolico \\
- \macro{S\_ISSOCK(m)} & socket \\
+ \macro{S\_ISSOCK(m)} & socket\index{socket} \\
\hline
\end{tabular}
\caption{Macro per i tipi di file (definite in \texttt{sys/stat.h}).}
\label{tab:file_type_macro}
\end{table}
-Oltre alle macro di \tabref{tab:file_type_macro} è possibile usare
+Oltre alle macro di tab.~\ref{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
-\tabref{tab:file_mode_flags}.
+tab.~\ref{tab:file_mode_flags}.
-Il primo valore dell'elenco di \tabref{tab:file_mode_flags} è la maschera
+Il primo valore dell'elenco di tab.~\ref{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
\textbf{Flag} & \textbf{Valore} & \textbf{Significato} \\
\hline
\hline
- \macro{S\_IFMT} & 0170000 & bitmask per i bit del tipo di file \\
- \macro{S\_IFSOCK} & 0140000 & socket \\
- \macro{S\_IFLNK} & 0120000 & link simbolico \\
- \macro{S\_IFREG} & 0100000 & file regolare \\
- \macro{S\_IFBLK} & 0060000 & device a blocchi \\
- \macro{S\_IFDIR} & 0040000 & directory \\
- \macro{S\_IFCHR} & 0020000 & device a caratteri \\
- \macro{S\_IFIFO} & 0010000 & fifo \\
+ \const{S\_IFMT} & 0170000 & maschera per i bit del tipo di file \\
+ \const{S\_IFSOCK} & 0140000 & socket\index{socket} \\
+ \const{S\_IFLNK} & 0120000 & link simbolico \\
+ \const{S\_IFREG} & 0100000 & file regolare \\
+ \const{S\_IFBLK} & 0060000 & dispositivo a blocchi \\
+ \const{S\_IFDIR} & 0040000 & directory \\
+ \const{S\_IFCHR} & 0020000 & dispositivo a caratteri \\
+ \const{S\_IFIFO} & 0010000 & fifo \\
\hline
- \macro{S\_ISUID} & 0004000 & set UID bit \\
- \macro{S\_ISGID} & 0002000 & set GID bit \\
- \macro{S\_ISVTX} & 0001000 & sticky bit \\
+ \const{S\_ISUID} & 0004000 & set UID bit \\
+ \const{S\_ISGID} & 0002000 & set GID bit \\
+ \const{S\_ISVTX} & 0001000 & sticky bit \\
\hline
-% \macro{S\_IRWXU} & 00700 & bitmask per i permessi del proprietario \\
- \macro{S\_IRUSR} & 00400 & il proprietario ha permesso di lettura \\
- \macro{S\_IWUSR} & 00200 & il proprietario ha permesso di scrittura \\
- \macro{S\_IXUSR} & 00100 & il proprietario ha permesso di esecuzione\\
+% \const{S\_IRWXU} & 00700 & bitmask per i permessi del proprietario \\
+ \const{S\_IRUSR} & 00400 & il proprietario ha permesso di lettura \\
+ \const{S\_IWUSR} & 00200 & il proprietario ha permesso di scrittura \\
+ \const{S\_IXUSR} & 00100 & il proprietario ha permesso di esecuzione\\
\hline
-% \macro{S\_IRWXG} & 00070 & bitmask per i permessi del gruppo \\
- \macro{S\_IRGRP} & 00040 & il gruppo ha permesso di lettura \\
- \macro{S\_IWGRP} & 00020 & il gruppo ha permesso di scrittura \\
- \macro{S\_IXGRP} & 00010 & il gruppo ha permesso di esecuzione \\
+% \const{S\_IRWXG} & 00070 & bitmask per i permessi del gruppo \\
+ \const{S\_IRGRP} & 00040 & il gruppo ha permesso di lettura \\
+ \const{S\_IWGRP} & 00020 & il gruppo ha permesso di scrittura \\
+ \const{S\_IXGRP} & 00010 & il gruppo ha permesso di esecuzione \\
\hline
-% \macro{S\_IRWXO} & 00007 & bitmask per i permessi di tutti gli altri\\
- \macro{S\_IROTH} & 00004 & gli altri hanno permesso di lettura \\
- \macro{S\_IWOTH} & 00002 & gli altri hanno permesso di esecuzione \\
- \macro{S\_IXOTH} & 00001 & gli altri hanno permesso di esecuzione \\
+% \const{S\_IRWXO} & 00007 & bitmask per i permessi di tutti gli altri\\
+ \const{S\_IROTH} & 00004 & gli altri hanno permesso di lettura \\
+ \const{S\_IWOTH} & 00002 & gli altri hanno permesso di esecuzione \\
+ \const{S\_IXOTH} & 00001 & gli altri hanno permesso di esecuzione \\
\hline
\end{tabular}
\caption{Costanti per l'identificazione dei vari bit che compongono il campo
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}
+\includecodesnip{listati/is_file_dir.h}
in cui prima si estraggono da \var{st\_mode} i bit relativi al tipo di file e
poi si effettua il confronto con la combinazione di tipi scelta.
\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 regolare, nel caso di un link simbolico la dimensione è quella del
-pathname che contiene).
+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
+\index{\textit{pathname}}\textit{pathname} che contiene, per le fifo è sempre
+nullo).
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
detto che corrisponda all'occupazione dello spazio su disco per via della
possibile 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
+dopo aver eseguito una \func{lseek} (vedi sez.~\ref{sec:file_lseek}) oltre la
sua fine.
In questo caso si avranno risultati differenti a seconda del modo in cui si
presenti al di là della dimensione scelta come nuova fine del file.
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 \func{truncate} e
-\func{ftruncate}, i cui prototipi sono:
+\const{O\_TRUNC}, ma questo è un caso particolare; per qualunque altra
+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[\macro{EBADF}] \var{fd} non è un file descriptor.
- \item[\macro{EINVAL}] \var{fd} è un riferimento ad un socket, non a un file
- o non è aperto in scrittura.
+ \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:
\begin{errlist}
- \item[\macro{EACCES}] il file non ha permesso di scrittura o non si ha il
- permesso di esecuzione una delle directory del pathname.
- \item[\macro{ETXTBSY}] Il file è un programma in esecuzione.
+ \item[\errcode{EACCES}] il file non ha permesso di scrittura o non si ha il
+ permesso di esecuzione una delle directory del
+ \index{\textit{pathname}}\textit{pathname}.
+ \item[\errcode{ETXTBSY}] Il file è un programma in esecuzione.
\end{errlist}
- ed anche \macro{ENOTDIR}, \macro{ENAMETOOLONG}, \macro{ENOENT},
- \macro{EROFS}, \macro{EIO}, \macro{EFAULT}, \macro{ELOOP}.}
+ ed anche \errval{ENOTDIR}, \errval{ENAMETOOLONG}, \errval{ENOENT},
+ \errval{EROFS}, \errval{EIO}, \errval{EFAULT}, \errval{ELOOP}.}
\end{functions}
Se il file è più lungo della lunghezza specificata i dati in eccesso saranno
\label{sec:file_file_times}
Il sistema mantiene per ciascun file tre tempi. Questi sono registrati
-nell'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
-\tabref{tab:file_file_times}, dove si è anche riportato un esempio delle
+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 \struct{stat} di fig.~\ref{fig:file_stat_struct}. Il
+significato di detti tempi e dei relativi campi è riportato nello schema in
+tab.~\ref{tab:file_file_times}, dove è anche riportato un esempio delle
funzioni che effettuano cambiamenti su di essi.
\begin{table}[htb]
modifica (il \textit{modification time} \var{st\_mtime}) e il tempo di
cambiamento di stato (il \textit{change time} \var{st\_ctime}). Il primo
infatti fa riferimento ad una modifica del contenuto di un file, mentre il
-secondo ad una modifica dell'inode; siccome esistono molte operazioni (come la
-funzione \func{link} e molte altre che vedremo in seguito) che modificano solo
-le informazioni contenute nell'inode senza toccare il file, diventa necessario
-l'utilizzo di un altro tempo.
+secondo ad una modifica dell'inode\index{inode}; siccome esistono molte
+operazioni (come la funzione \func{link} e molte altre che vedremo in seguito)
+che modificano solo le informazioni contenute nell'inode\index{inode} senza
+toccare il file, diventa necessario l'utilizzo di un altro tempo.
-Il sistema non tiene conto dell'ultimo accesso all'inode, pertanto funzioni
-come \func{access} o \func{stat} non hanno alcuna influenza sui tre tempi. Il
-tempo di ultimo accesso (ai dati) viene di solito usato per cancellare i file
-che non servono più dopo un certo lasso di tempo (ad esempio \cmd{leafnode}
-cancella i vecchi articoli sulla base di questo tempo).
+Il sistema non tiene conto dell'ultimo accesso all'inode\index{inode},
+pertanto funzioni come \func{access} o \func{stat} non hanno alcuna influenza
+sui tre tempi. Il tempo di ultimo accesso (ai dati) viene di solito usato per
+cancellare i file che non servono più dopo un certo lasso di tempo (ad esempio
+\cmd{leafnode} cancella i vecchi articoli sulla base di questo tempo).
Il tempo di ultima modifica invece viene usato da \cmd{make} per decidere
quali file necessitano di essere ricompilati o (talvolta insieme anche al
tempo di cambiamento di stato) per decidere quali file devono essere
archiviati per il backup. Il comando \cmd{ls} (quando usato con le opzioni
\cmd{-l} o \cmd{-t}) mostra i tempi dei file secondo lo schema riportato
-nell'ultima colonna di \tabref{tab:file_file_times}.
-
-L'effetto delle varie funzioni di manipolazione dei file sui tempi è
-illustrato in \tabref{tab:file_times_effects}. Si sono riportati gli effetti
-sia per il file a cui si fa riferimento, sia per la directory che lo contiene;
-questi ultimi possono essere capiti se si tiene conto di quanto già detto, e
-cioè che anche le directory sono file (che contengono una lista di nomi) che
-il sistema tratta in maniera del tutto analoga a tutti gli altri.
-
-Per questo motivo tutte le volte che compiremo un'operazione su un file che
-comporta una modifica del nome contenuto nella directory, andremo anche a
-scrivere sulla directory che lo contiene cambiandone il tempo di modifica. Un
-esempio di questo può essere la cancellazione di un file, invece leggere o
-scrivere o cambiare i permessi di un file ha effetti solo sui tempi di
-quest'ultimo.
+nell'ultima colonna di tab.~\ref{tab:file_file_times}.
\begin{table}[htb]
\centering
\hline
\hline
\func{chmod}, \func{fchmod}
- & & &$\bullet$& & & & \\
+ & -- & -- &$\bullet$& -- & -- & -- & \\
\func{chown}, \func{fchown}
- & & &$\bullet$& & & & \\
+ & -- & -- &$\bullet$& -- & -- & -- & \\
\func{creat}
- &$\bullet$&$\bullet$&$\bullet$& &$\bullet$&$\bullet$& con
- \macro{O\_CREATE} \\ \func{creat}
- & &$\bullet$&$\bullet$& &$\bullet$&$\bullet$&
- con \macro{O\_TRUNC} \\ \func{exec}
- &$\bullet$& & & & & & \\
+ &$\bullet$&$\bullet$&$\bullet$& -- &$\bullet$&$\bullet$& con
+ \const{O\_CREATE} \\ \func{creat}
+ & -- &$\bullet$&$\bullet$& -- &$\bullet$&$\bullet$&
+ con \const{O\_TRUNC} \\ \func{exec}
+ &$\bullet$& -- & -- & -- & -- & -- & \\
\func{lchown}
- & & &$\bullet$& & & & \\
+ & -- & -- &$\bullet$& -- & -- & -- & \\
\func{link}
- & & &$\bullet$& &$\bullet$&$\bullet$& \\
+ & -- & -- &$\bullet$& -- &$\bullet$&$\bullet$& \\
\func{mkdir}
- &$\bullet$&$\bullet$&$\bullet$& &$\bullet$&$\bullet$& \\
+ &$\bullet$&$\bullet$&$\bullet$& -- &$\bullet$&$\bullet$& \\
\func{mkfifo}
- &$\bullet$&$\bullet$&$\bullet$& &$\bullet$&$\bullet$& \\
+ &$\bullet$&$\bullet$&$\bullet$& -- &$\bullet$&$\bullet$& \\
\func{open}
- &$\bullet$&$\bullet$&$\bullet$& &$\bullet$&$\bullet$& con
- \macro{O\_CREATE} \\ \func{open}
- & &$\bullet$&$\bullet$& & & & con
- \macro{O\_TRUNC} \\ \func{pipe}
- &$\bullet$&$\bullet$&$\bullet$& & & & \\
+ &$\bullet$&$\bullet$&$\bullet$& -- &$\bullet$&$\bullet$& con
+ \const{O\_CREATE} \\ \func{open}
+ & -- &$\bullet$&$\bullet$& -- & -- & -- & con
+ \const{O\_TRUNC} \\ \func{pipe}
+ &$\bullet$&$\bullet$&$\bullet$& -- & -- & -- & \\
\func{read}
- &$\bullet$& & & & & & \\
+ &$\bullet$& -- & -- & -- & -- & -- & \\
\func{remove}
- & & &$\bullet$& &$\bullet$&$\bullet$& se esegue
+ & -- & -- &$\bullet$& -- &$\bullet$&$\bullet$& se esegue
\func{unlink}\\ \func{remove}
- & & & & &$\bullet$&$\bullet$& se esegue
+ & -- & -- & -- & -- &$\bullet$&$\bullet$& se esegue
\func{rmdir}\\ \func{rename}
- & & &$\bullet$& &$\bullet$&$\bullet$& per entrambi
+ & -- & -- &$\bullet$& -- &$\bullet$&$\bullet$& per entrambi
gli argomenti\\ \func{rmdir}
- & & & & &$\bullet$&$\bullet$& \\
+ & -- & -- & -- & -- &$\bullet$&$\bullet$& \\
\func{truncate}, \func{ftruncate}
- & &$\bullet$&$\bullet$& & & & \\
+ & -- &$\bullet$&$\bullet$& -- & -- & -- & \\
\func{unlink}
- & & &$\bullet$& &$\bullet$&$\bullet$& \\
+ & -- & -- &$\bullet$& -- &$\bullet$&$\bullet$& \\
\func{utime}
- &$\bullet$&$\bullet$&$\bullet$& & & & \\
+ &$\bullet$&$\bullet$&$\bullet$& -- & -- & -- & \\
\func{write}
- & &$\bullet$&$\bullet$& & & & \\
+ & -- &$\bullet$&$\bullet$& -- & -- & -- & \\
\hline
\end{tabular}
\caption{Prospetto dei cambiamenti effettuati sui tempi di ultimo
\label{tab:file_times_effects}
\end{table}
+L'effetto delle varie funzioni di manipolazione dei file sui tempi è
+illustrato in tab.~\ref{tab:file_times_effects}. Si sono riportati gli effetti
+sia per il file a cui si fa riferimento, sia per la directory che lo contiene;
+questi ultimi possono essere capiti se si tiene conto di quanto già detto, e
+cioè che anche le directory sono file (che contengono una lista di nomi) che
+il sistema tratta in maniera del tutto analoga a tutti gli altri.
+
+Per questo motivo tutte le volte che compiremo un'operazione su un file che
+comporta una modifica del nome contenuto nella directory, andremo anche a
+scrivere sulla directory che lo contiene cambiandone il tempo di modifica. Un
+esempio di questo può essere la cancellazione di un file, invece leggere o
+scrivere o cambiare i permessi di un file ha effetti solo sui tempi di
+quest'ultimo.
+
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
esiste. Per questo motivo quando si copia un file, a meno di preservare
\label{sec:file_utime}
I tempi di ultimo accesso e modifica possono essere cambiati usando la
-funzione \func{utime}, il cui prototipo è:
+funzione \funcd{utime}, il cui prototipo è:
\begin{prototype}{utime.h}
{int utime(const char *filename, struct utimbuf *times)}
-Cambia i tempi di ultimo accesso e modifica dell'inode specificato da
-\param{filename} secondo i campi \var{actime} e \var{modtime} di
-\param{times}. Se questa è \macro{NULL} allora viene usato il tempo corrente.
+Cambia i tempi di ultimo accesso e modifica dell'inode\index{inode}
+specificato da \param{filename} secondo i campi \var{actime} e \var{modtime}
+di \param{times}. Se questa è \val{NULL} allora viene usato il tempo corrente.
\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
errore, nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
- \item[\macro{EACCESS}] non si ha il permesso di scrittura sul file.
- \item[\macro{ENOENT}] \param{filename} non esiste.
+ \item[\errcode{EACCES}] non si ha il permesso di scrittura sul file.
+ \item[\errcode{ENOENT}] \param{filename} non esiste.
\end{errlist}}
\end{prototype}
-
-La struttura \var{utimebuf} usata da \func{utime} è definita come:
-\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-struct utimbuf {
- time_t actime; /* access time */
- time_t modtime; /* modification time */
-};
-\end{lstlisting}
+
+La funzione prende come argomento \param{times} una struttura
+\struct{utimebuf}, la cui definizione è riportata in
+fig.~\ref{fig:struct_utimebuf}, con la quale si possono specificare i nuovi
+valori che si vogliono impostare per tempi.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includestruct{listati/utimbuf.h}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \structd{utimbuf}, usata da \func{utime} per modificare
+ i tempi dei file.}
+ \label{fig:struct_utimebuf}
+\end{figure}
L'effetto della funzione e i privilegi necessari per eseguirla dipendono da
-cosa è l'argomento \param{times}; se è \macro{NULL} la funzione imposta il
+cosa è l'argomento \param{times}; se è \val{NULL} la funzione imposta 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).
Si tenga presente che non è comunque possibile specificare il tempo di
cambiamento di stato del file, che viene comunque cambiato dal kernel tutte le
-volte che si modifica l'inode (quindi anche alla chiamata di \func{utime}).
-Questo serve anche come misura di sicurezza per evitare che si possa
-modificare un file nascondendo completamente le proprie tracce. In realtà la
-cosa resta possibile, se si è in grado di accedere al device, scrivendo
-direttamente sul disco senza passare attraverso il filesystem, ma ovviamente
-in questo modo la cosa è molto più complicata da realizzare.
+volte che si modifica l'inode\index{inode} (quindi anche alla chiamata di
+\func{utime}). Questo serve anche come misura di sicurezza per evitare che si
+possa modificare un file nascondendo completamente le proprie tracce. In
+realtà la cosa resta possibile, se si è in grado di accedere al file di
+dispositivo, scrivendo direttamente sul disco senza passare attraverso il
+filesystem, ma ovviamente in questo modo la cosa è molto più complicata da
+realizzare.
Una delle caratteristiche fondamentali di tutti i sistemi unix-like è quella
del controllo di accesso ai file, che viene implementato per qualunque
-filesystem standard. In questa sezione ne esamineremo i concetti essenziali e
-le funzioni usate per gestirne i vari aspetti.
+filesystem standard.\footnote{per standard si intende che implementa le
+ caratteristiche previste dallo standard POSIX. In Linux sono disponibili
+ anche una serie di altri filesystem, come quelli di Windows e del Mac, che
+ non supportano queste caratteristiche.} In questa sezione ne esamineremo i
+concetti essenziali e le funzioni usate per gestirne i vari aspetti.
\subsection{I permessi per l'accesso ai file}
Ad ogni file Linux associa sempre l'utente che ne è proprietario (il
cosiddetto \textit{owner}) ed un gruppo di appartenenza, secondo il meccanismo
-degli identificatori di utenti e gruppi (\acr{uid} e \acr{gid}). Questi valori
+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 sez.~\ref{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.
Esistono varie estensioni a questo modello,\footnote{come le \textit{Access
Control List} che possono essere aggiunte al filesystem standard con
- opportune patch, e sono presenti in filesystem non ancora inclusi nel kernel
- ufficiale come \textsl{xfs}, o meccanismi di controllo ancora più
- sofisticati come il \textit{mandatory access control} di SE-Linux.} ma nella
-maggior parte dei casi il meccanismo standard è più che sufficiente a
-soffisfare tutte le necessità più comuni. I tre permessi di base associati ad
-ogni file sono:
+ opportune patch, la cui introduzione nei kernel ufficiali è iniziata con la
+ serie 2.5.x. per arrivare a meccanismi di controllo ancora più sofisticati
+ come il \textit{mandatory access control} di SE-Linux.} ma nella maggior
+parte dei casi il meccanismo standard è più che sufficiente a soddisfare tutte
+le necessità più comuni. I tre permessi di base associati ad ogni file sono:
\begin{itemize*}
\item il permesso di lettura (indicato con la lettera \texttt{r}, dall'inglese
\textit{read}).
lettura, scrittura ed esecuzione e sono applicati rispettivamente
rispettivamente al proprietario, al gruppo, a tutti gli altri.
+\begin{figure}[htb]
+ \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 \struct{fstat}.}
+ \label{fig:file_perm_bit}
+\end{figure}
+
I restanti tre bit (noti come \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}).
+sez.~\ref{sec:file_suid_sgid} e sez.~\ref{sec:file_sticky}); lo schema di
+allocazione dei bit è riportato in fig.~\ref{fig:file_perm_bit}.
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 di nuovo
-\figref{fig:file_stat_struct}).
+memorizzati nell'inode\index{inode}; in particolare essi sono contenuti in
+alcuni bit del campo \var{st\_mode} della struttura \struct{stat} (si veda di
+nuovo fig.~\ref{fig:file_stat_struct}).
In genere ci si riferisce ai tre livelli dei privilegi usando le lettere
\cmd{u} (per \textit{user}), \cmd{g} (per \textit{group}) e \cmd{o} (per
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 \tabref{tab:file_bit_perm}.
+\var{st\_mode} sono riportate in tab.~\ref{tab:file_bit_perm}.
\begin{table}[htb]
\centering
\textbf{\var{st\_mode}} bit & \textbf{Significato} \\
\hline
\hline
- \macro{S\_IRUSR} & \textit{user-read}, l'utente può leggere \\
- \macro{S\_IWUSR} & \textit{user-write}, l'utente può scrivere \\
- \macro{S\_IXUSR} & \textit{user-execute}, l'utente può eseguire \\
+ \const{S\_IRUSR} & \textit{user-read}, l'utente può leggere \\
+ \const{S\_IWUSR} & \textit{user-write}, l'utente può scrivere \\
+ \const{S\_IXUSR} & \textit{user-execute}, l'utente può eseguire \\
\hline
- \macro{S\_IRGRP} & \textit{group-read}, il gruppo può leggere \\
- \macro{S\_IWGRP} & \textit{group-write}, il gruppo può scrivere \\
- \macro{S\_IXGRP} & \textit{group-execute}, il gruppo può eseguire\\
+ \const{S\_IRGRP} & \textit{group-read}, il gruppo può leggere \\
+ \const{S\_IWGRP} & \textit{group-write}, il gruppo può scrivere \\
+ \const{S\_IXGRP} & \textit{group-execute}, il gruppo può eseguire\\
\hline
- \macro{S\_IROTH} & \textit{other-read}, tutti possono leggere \\
- \macro{S\_IWOTH} & \textit{other-write}, tutti possono scrivere \\
- \macro{S\_IXOTH} & \textit{other-execute}, tutti possono eseguire\\
+ \const{S\_IROTH} & \textit{other-read}, tutti possono leggere \\
+ \const{S\_IWOTH} & \textit{other-write}, tutti possono scrivere \\
+ \const{S\_IXOTH} & \textit{other-execute}, tutti possono eseguire\\
\hline
\end{tabular}
\caption{I bit dei permessi di accesso ai file, come definiti in
\end{table}
I permessi vengono usati in maniera diversa dalle varie funzioni, e a seconda
-che si riferiscano a dei file, dei link simbolici o delle directory, qui ci
+che si riferiscano a dei file, dei link simbolici o delle directory; qui ci
limiteremo ad un riassunto delle regole generali, entrando nei dettagli più
avanti.
-La prima regola è che per poter accedere ad un file attraverso il suo pathname
-occorre il permesso di esecuzione in ciascuna delle directory che compongono
-il pathname; lo stesso vale per aprire un file nella directory corrente (per
-la quale appunto serve il diritto di esecuzione).
+La prima regola è che per poter accedere ad un file attraverso il suo
+\textit{pathname} occorre il permesso di esecuzione in ciascuna delle
+directory che compongono il \textit{pathname}; lo stesso vale per aprire un
+file nella directory corrente (per la quale appunto serve il diritto di
+esecuzione).
Per una directory infatti il permesso di esecuzione significa che essa può
-essere attraversata nella risoluzione del pathname, ed è distinto dal permesso
-di lettura che invece implica che si può leggere il contenuto della directory.
+essere attraversata nella risoluzione del
+\index{\textit{pathname}}\textit{pathname}, ed è distinto dal permesso di
+lettura che invece implica che si può leggere il contenuto della directory.
+
Questo significa che se si ha il permesso di esecuzione senza permesso di
lettura si potrà lo stesso aprire un file in una directory (se si hanno i
permessi opportuni per il medesimo) ma non si potrà vederlo con \cmd{ls}
directory).
Avere il permesso di lettura per un file consente di aprirlo con le opzioni
-(si veda quanto riportato in \tabref{tab:file_open_flags}) di sola lettura o
+(si veda quanto riportato in tab.~\ref{tab:file_open_flags}) di sola lettura o
di lettura/scrittura e leggerne il contenuto. Avere il permesso di scrittura
consente di aprire un file in sola scrittura o lettura/scrittura e modificarne
il contenuto, lo stesso permesso è necessario per poter troncare il file.
appartiene vengono pure ignorati quando il link viene risolto, vengono
controllati solo quando viene richiesta la rimozione del link e quest'ultimo è
in una directory con lo \textsl{sticky bit} impostato (si veda
-\secref{sec:file_sticky}).
+sez.~\ref{sec:file_sticky}).
La procedura con cui il kernel stabilisce se un processo possiede un certo
permesso (di lettura, scrittura o esecuzione) si basa sul confronto fra
l'utente e il gruppo a cui il file appartiene (i valori di \var{st\_uid} e
-\var{st\_gid} accennati in precedenza) e l'userid effettivo, il groupid
-effettivo e gli eventuali groupid supplementari del processo.\footnote{in
- realtà Linux, per quanto riguarda l'accesso ai file, utilizza gli gli
+\var{st\_gid} accennati in precedenza) e l'user-ID effettivo, il group-ID
+effettivo e gli eventuali group-ID supplementari del processo.\footnote{in
+ realtà Linux, per quanto riguarda l'accesso ai file, utilizza gli
identificatori del gruppo \textit{filesystem} (si ricordi quanto esposto in
- \secref{sec:proc_perms}), ma essendo questi del tutto equivalenti ai primi,
+ sez.~\ref{sec:proc_perms}), ma essendo questi del tutto equivalenti ai primi,
eccetto il caso in cui si voglia scrivere un server NFS, ignoreremo questa
differenza.}
Per una spiegazione dettagliata degli identificatori associati ai processi si
-veda \secref{sec:proc_perms}; normalmente, a parte quanto vedremo in
-\secref{sec:file_suid_sgid}, l'userid effettivo e il groupid effectivo
+veda sez.~\ref{sec:proc_perms}; normalmente, a parte quanto vedremo in
+sez.~\ref{sec:file_suid_sgid}, l'user-ID effettivo e il group-ID effettivo
corrispondono ai valori dell'\acr{uid} e del \acr{gid} dell'utente che ha
-lanciato il processo, mentre i groupid supplementari sono quelli dei gruppi
+lanciato il processo, mentre i group-ID supplementari sono quelli dei gruppi
cui l'utente appartiene.
I passi attraverso i quali viene stabilito se il processo possiede il diritto
di accesso sono i seguenti:
\begin{enumerate}
-\item Se l'userid effettivo del processo è zero (corrispondente
+\item Se l'user-ID effettivo 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
tutti i file.
-\item Se l'userid effettivo del processo è uguale all'\acr{uid} del
+\item Se l'user-ID effettivo del processo è uguale all'\acr{uid} del
proprietario del file (nel qual caso si dice che il processo è proprietario
del file) allora:
\begin{itemize*}
impostato, l'accesso è consentito
\item altrimenti l'accesso è negato
\end{itemize*}
-\item Se il groupid effettivo del processo o uno dei groupid supplementari dei
- processi corrispondono al \acr{gid} del file allora:
+\item Se il group-ID effettivo del processo o uno dei group-ID supplementari
+ dei processi corrispondono al \acr{gid} del file allora:
\begin{itemize*}
\item se il bit dei permessi d'accesso del gruppo è impostato, l'accesso è
consentito,
\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
+quest'ordine. Questo vuol dire che se un processo è il proprietario di un file,
l'accesso è consentito o negato solo sulla base dei permessi per l'utente; i
permessi per il gruppo non vengono neanche controllati. Lo stesso vale se il
processo appartiene ad un gruppo appropriato, in questo caso i permessi per
\subsection{I bit \acr{suid} e \acr{sgid}}
\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
+Come si è accennato (in sez.~\ref{sec:file_perm_overview}) nei dodici bit del
+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
\textit{set-group-ID bit}) che sono identificati dalle costanti
-\macro{S\_ISUID} e \macro{S\_ISGID}.
+\const{S\_ISUID} e \const{S\_ISGID}.
-Come spiegato in dettaglio in \secref{sec:proc_exec}, quando si lancia un
+Come spiegato in dettaglio in sez.~\ref{sec:proc_exec}, quando si lancia un
programma il comportamento normale del kernel è quello di impostare gli
identificatori del gruppo \textit{effective} del nuovo processo al valore dei
corrispondenti del gruppo \textit{real} del processo corrente, che normalmente
-corrispondono dell'utente con cui si è entrati nel sistema.
+corrispondono a quelli dell'utente con cui si è entrati nel sistema.
-Se però il file del programma\footnote{per motivi di sicurezza il kernel
- ignora i bit \acr{suid} e \acr{sgid} per gli script eseguibili.} (che
-ovviamente deve essere eseguibile) ha il bit \acr{suid} impostato, il kernel
-assegnerà come userid effettivo al nuovo processo l'\acr{uid} del proprietario
-del file al posto dell'\acr{uid} del processo originario. Avere il bit
-\acr{sgid} impostato ha lo stesso effetto sul groupid effettivo del processo.
+Se però il file del programma (che ovviamente deve essere
+eseguibile\footnote{per motivi di sicurezza il kernel ignora i bit \acr{suid}
+ e \acr{sgid} per gli script eseguibili.}) ha il bit \acr{suid} impostato, il
+kernel assegnerà come user-ID effettivo al nuovo processo l'\acr{uid} del
+proprietario del file al posto dell'\acr{uid} del processo originario. Avere
+il bit \acr{sgid} impostato ha lo stesso effetto sul group-ID effettivo del
+processo.
I bit \acr{suid} e \acr{sgid} vengono usati per permettere agli utenti normali
-di usare programmi che abbisognano di privilegi speciali; l'esempio classico è
-il comando \cmd{passwd} che ha la necessità di modificare il file delle
-password, quest'ultimo ovviamente può essere scritto solo dall'amministratore,
-ma non è necessario chiamare l'amministratore per cambiare la propria
-password. Infatti il comando \cmd{passwd} appartiene a root ma ha il bit
-\acr{suid} impostato per cui quando viene lanciato da un utente normale parte
-con i privilegi di root.
+di usare programmi che richiedono privilegi speciali; l'esempio classico è il
+comando \cmd{passwd} che ha la necessità di modificare il file delle password,
+quest'ultimo ovviamente può essere scritto solo dall'amministratore, ma non è
+necessario chiamare l'amministratore per cambiare la propria password. Infatti
+il comando \cmd{passwd} appartiene a root ma ha il bit \acr{suid} impostato
+per cui quando viene lanciato da un utente normale parte con i privilegi di
+root.
Chiaramente avere un processo che ha privilegi superiori a quelli che avrebbe
normalmente l'utente che lo ha lanciato comporta vari rischi, e questo tipo di
programmi devono essere scritti accuratamente per evitare che possano essere
usati per guadagnare privilegi non consentiti (l'argomento è affrontato in
-dettaglio in \secref{sec:proc_perms}).
+dettaglio in sez.~\ref{sec:proc_perms}).
La presenza dei bit \acr{suid} e \acr{sgid} su un file può essere rilevata con
il comando \cmd{ls -l}, che visualizza una lettera \cmd{s} al posto della
\cmd{x} in corrispondenza dei permessi di utente o gruppo. La stessa lettera
\cmd{s} può essere usata nel comando \cmd{chmod} per impostare questi bit.
Infine questi bit possono essere controllati all'interno di \var{st\_mode} con
-l'uso delle due costanti \macro{S\_ISUID} e \macro{S\_IGID}, i cui valori sono
-riportati in \tabref{tab:file_mode_flags}.
+l'uso delle due costanti \const{S\_ISUID} e \const{S\_IGID}, i cui valori sono
+riportati in tab.~\ref{tab:file_mode_flags}.
Gli stessi bit vengono ad assumere in significato completamente diverso per le
-directory, normalmente infatti Linux usa la convenzione di SVR4 per indicare
+directory, normalmente infatti Linux usa la convenzione di SVr4 per indicare
con questi bit l'uso della semantica BSD nella creazione di nuovi file (si
-veda \secref{sec:file_ownership} per una spiegazione dettagliata al
+veda sez.~\ref{sec:file_ownership} per una spiegazione dettagliata al
proposito).
Infine Linux utilizza il bit \acr{sgid} per una ulteriore estensione mutuata
-da SVr4. Il caso in cui un file ha il bit \acr{sgid} impostare senza che lo sia
-anche il corrispondente bit di esecuzione viene utilizzato per attivare per
-quel file il \textit{mandatory locking} (argomento che affronteremo in
-dettagliopiù avanti in \secref{sec:file_mand_locking}).
+da SVr4. Il caso in cui un file ha il bit \acr{sgid} impostato senza che lo
+sia anche il corrispondente bit di esecuzione viene utilizzato per attivare
+per quel file il \textit{mandatory locking} (affronteremo questo argomento in
+dettaglio più avanti, in sez.~\ref{sec:file_mand_locking}).
\subsection{Il bit \textsl{sticky}}
\label{sec:file_sticky}
-L'ultimo dei bit rimanenti, identificato dalla costante \macro{S\_ISVTX}, è in
+L'ultimo dei bit rimanenti, identificato dalla costante \const{S\_ISVTX}, è in
parte un rimasuglio delle origini dei sistemi Unix. A quell'epoca infatti la
memoria virtuale e l'accesso ai files erano molto meno sofisticati e per
ottenere la massima velocità possibile per i programmi usati più comunemente
si poteva impostare questo bit.
L'effetto di questo bit era che il segmento di testo del programma (si veda
-\secref{sec:proc_mem_layout} per i dettagli) veniva scritto nella swap la
+sez.~\ref{sec:proc_mem_layout} per i dettagli) veniva scritto nella swap la
prima volta che questo veniva lanciato, e vi permaneva fino al riavvio della
macchina (da questo il nome di \textsl{sticky bit}); essendo la swap un file
continuo indicizzato direttamente in questo modo si poteva risparmiare in
Benché ormai non venga più utilizzato per i file, lo \textsl{sticky bit} ha
invece assunto un uso importante per le directory;\footnote{lo \textsl{sticky
bit} per le directory è un'estensione non definita nello standard POSIX,
- Linux però la supporta, così come BSD e SVR4.} in questo caso se il bit è
+ Linux però la supporta, così come BSD e SVr4.} in questo caso se tale bit è
impostato un file potrà essere rimosso dalla directory soltanto se l'utente ha
il permesso di scrittura su di essa ed inoltre è vera una delle seguenti
condizioni:
\item l'utente è l'amministratore
\end{itemize*}
un classico esempio di directory che ha questo bit impostato è \file{/tmp}, i
-permessi infatti di solito sono impostati come:
+permessi infatti di solito sono i seguenti:
\begin{verbatim}
$ ls -ld /tmp
drwxrwxrwt 6 root root 1024 Aug 10 01:03 /tmp
\end{verbatim}%$
-in questo modo chiunque può creare file in questa directory (che infatti è
-normalmente utilizzata per la creazione di file temporanei), ma solo l'utente
-che ha creato un certo file potrà cancellarlo o rinominarlo. In questo modo si
-evita che un utente possa, più o meno consapevolmente, cancellare i file degli
-altri.
+quindi con lo \textsl{sticky bit} bit impostato. In questo modo qualunque
+utente nel sistema può creare dei file in questa directory (che, come
+suggerisce il nome, è normalmente utilizzata per la creazione di file
+temporanei), ma solo l'utente che ha creato un certo file potrà cancellarlo o
+rinominarlo. In questo modo si evita che un utente possa, più o meno
+consapevolmente, cancellare i file temporanei creati degli altri utenti.
\subsection{La titolarità di nuovi file e directory}
\label{sec:file_ownership}
-Vedremo in \secref{sec:file_base_func} con quali funzioni si possono creare
+Vedremo in sez.~\ref{sec:file_base_func} con quali funzioni si possono creare
nuovi file, in tale occasione vedremo che è possibile specificare in sede di
creazione quali permessi applicare ad un file, però non si può indicare a
-quale utente e gruppo esso deve appartenere. Lo stesso problema di presenta
+quale utente e gruppo esso deve appartenere. Lo stesso problema si presenta
per la creazione di nuove directory (procedimento descritto in
-\secref{sec:file_dir_creat_rem}).
+sez.~\ref{sec:file_dir_creat_rem}).
Lo standard POSIX prescrive che l'\acr{uid} del nuovo file corrisponda
-all'userid effettivo del processo che lo crea; per il \acr{gid} invece prevede
+all'user-ID effettivo del processo che lo crea; per il \acr{gid} invece prevede
due diverse possibilità:
\begin{itemize*}
-\item il \acr{gid} del file corrisponde al group id effettivo del processo.
+\item il \acr{gid} del file corrisponde al group-ID effettivo del processo.
\item il \acr{gid} del file corrisponde al \acr{gid} della directory in cui
esso è creato.
\end{itemize*}
Usare la semantica BSD ha il vantaggio che il \acr{gid} viene sempre
automaticamente propagato, restando coerente a quello della directory di
-partenza, in tutte le sottodirectory. La semantica SVr4 offre la possibilità
-di scegliere, ma per ottenere lo stesso risultato di coerenza che si ha con
-BSD necessita che per le nuove directory venga anche propagato anche il bit
-\acr{sgid}. Questo è il comportamento predefinito di \func{mkdir}, ed è in
-questo modo ad esempio che Debian assicura che le sottodirectory create nelle
-home di un utente restino sempre con il \acr{gid} del gruppo primario dello
-stesso.
+partenza, in tutte le sotto-directory.
+
+La semantica SVr4 offre la possibilità di scegliere, ma per ottenere lo stesso
+risultato di coerenza che si ha con BSD necessita che per le nuove directory
+venga anche propagato anche il bit \acr{sgid}. Questo è il comportamento
+predefinito del comando \cmd{mkdir}, ed è in questo modo ad esempio che Debian
+assicura che le sotto-directory create nella home di un utente restino sempre
+con il \acr{gid} del gruppo primario dello stesso.
\subsection{La funzione \func{access}}
\label{sec:file_access}
-Come visto in \secref{sec:file_access_control} il controllo di accesso ad un
-file viene fatto utilizzando l'userid ed il groupid effettivo del processo; ci
-sono casi però in cui si può voler effettuare il controllo con l'userid reale
-ed il groupid reale, vale a dire usando i valori di \acr{uid} e \acr{gid}
-relativi all'utente che ha lanciato il programma, e che, come accennato in
-\secref{sec:file_suid_sgid} e spiegato in dettaglio in
-\secref{sec:proc_perms}, non è detto siano uguali a quelli effettivi. Per far
-questo si può usare la funzione \func{access}, il cui prototipo è:
+Come visto in sez.~\ref{sec:file_access_control} il controllo di accesso ad un
+file viene fatto utilizzando l'user-ID ed il group-ID effettivo del processo;
+ci sono casi però in cui si può voler effettuare il controllo con l'user-ID
+reale ed il group-ID reale, vale a dire usando i valori di \acr{uid} e
+\acr{gid} relativi all'utente che ha lanciato il programma, e che, come
+accennato in sez.~\ref{sec:file_suid_sgid} e spiegato in dettaglio in
+sez.~\ref{sec:proc_perms}, non è detto siano uguali a quelli effettivi.
+
+Per far questo si può usare la funzione \funcd{access}, il cui prototipo è:
\begin{prototype}{unistd.h}
{int access(const char *pathname, int mode)}
-Verifica i permessi di accesso, indicati da \param{mode}, per il file indicato
-da \param{pathname}.
+Verifica i permessi di accesso.
\bodydesc{La funzione ritorna 0 se l'accesso è consentito, -1 se l'accesso non
è consentito ed in caso di errore; nel qual caso la variabile \var{errno}
assumerà i valori:
\begin{errlist}
- \item[\macro{EINVAL}] il valore di \param{mode} non è valido.
- \item[\macro{EACCES}] l'accesso al file non è consentito, o non si ha il
+ \item[\errcode{EINVAL}] il valore di \param{mode} non è valido.
+ \item[\errcode{EACCES}] l'accesso al file non è consentito, o non si ha il
permesso di attraversare una delle directory di \param{pathname}.
- \item[\macro{EROFS}] si è richiesto l'accesso in scrittura per un file su un
- filesystem montato in sola lettura.
+ \item[\errcode{EROFS}] si è richiesto l'accesso in scrittura per un file su
+ un filesystem montato in sola lettura.
\end{errlist}
- ed inoltre \macro{EFAULT}, \macro{ENAMETOOLONG}, \macro{ENOENT},
- \macro{ENOTDIR}, \macro{ELOOP}, \macro{EIO}.}
+ ed inoltre \errval{EFAULT}, \errval{ENAMETOOLONG}, \errval{ENOENT},
+ \errval{ENOTDIR}, \errval{ELOOP}, \errval{EIO}.}
\end{prototype}
-I valori possibili per l'argomento \param{mode} sono esprimibili come
-combinazione delle costanti numeriche riportate in
-\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 \macro{F\_OK}, o anche
-direttamente \func{stat}. Nel caso in cui \var{pathname} si riferisca ad un
-link simbolico, questo viene seguito ed il controllo è fatto sul file a cui
-esso fa riferimento.
+La funzione verifica i permessi di accesso, indicati da \param{mode}, per il
+file indicato da \param{pathname}. I valori possibili per l'argomento
+\param{mode} sono esprimibili come combinazione delle costanti numeriche
+riportate in tab.~\ref{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 \param{pathname} si
+riferisca ad un link simbolico, questo viene seguito ed il controllo è fatto
+sul file a cui esso fa riferimento.
La funzione controlla solo i bit dei permessi di accesso, si ricordi che il
fatto che una directory abbia permesso di scrittura non significa che ci si
\footnotesize
\begin{tabular}{|c|l|}
\hline
- \textbf{\var{mode}} & \textbf{Significato} \\
+ \textbf{\param{mode}} & \textbf{Significato} \\
\hline
\hline
- \macro{R\_OK} & verifica il permesso di lettura \\
- \macro{W\_OK} & verifica il permesso di scritture \\
- \macro{X\_OK} & verifica il permesso di esecuzione \\
- \macro{F\_OK} & verifica l'esistenza del file \\
+ \const{R\_OK} & verifica il permesso di lettura \\
+ \const{W\_OK} & verifica il permesso di scritture \\
+ \const{X\_OK} & verifica il permesso di esecuzione \\
+ \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:
\begin{errlist}
- \item[\macro{EPERM}] L'userid effettivo non corrisponde a quello del
+ \item[\errcode{EPERM}] L'user-ID effettivo non corrisponde a quello del
proprietario del file o non è zero.
+ \item[\errcode{EROFS}] Il file è su un filesystem in sola lettura.
\end{errlist}
- ed inoltre \macro{EROFS} e \macro{EIO}; \func{chmod} restituisce anche
- \macro{EFAULT}, \macro{ENAMETOOLONG}, \macro{ENOENT}, \macro{ENOMEM},
- \macro{ENOTDIR}, \macro{EACCES}, \macro{ELOOP}; \func{fchmod} anche
- \macro{EBADF}.}
+ ed inoltre \errval{EIO}; \func{chmod} restituisce anche \errval{EFAULT},
+ \errval{ENAMETOOLONG}, \errval{ENOENT}, \errval{ENOMEM}, \errval{ENOTDIR},
+ \errval{EACCES}, \errval{ELOOP}; \func{fchmod} anche \errval{EBADF}.}
\end{functions}
-I valori possibili per \var{mode} sono indicati in
-\tabref{tab:file_permission_const}. I valori possono esser combinati con l'OR
-binario delle relative costanti simboliche, o specificati direttamente, come
-per l'analogo comando di shell, con il valore numerico (la shell lo vuole in
-ottale, dato che i bit dei permessi sono divisibili in gruppi di tre). Ad
-esempio i permessi standard assegnati ai nuovi file (lettura e scrittura per
-il proprietario, sola lettura per il gruppo e gli altri) sono corrispondenti
-al valore ottale $0644$, un programma invece avrebbe anche il bit di
-esecuzione attivo, con un valore di $0755$, se si volesse attivare il bit
-\acr{suid} il valore da fornire sarebbe $4755$.
+Entrambe le funzioni utilizzano come secondo argomento \param{mode}, una
+variabile dell'apposito tipo primitivo \type{mode\_t} (vedi
+tab.~\ref{tab:intro_primitive_types}) utilizzato per specificare i permessi sui
+file.
\begin{table}[!htb]
\centering
\footnotesize
\begin{tabular}[c]{|c|c|l|}
\hline
- \textbf{\var{mode}} & \textbf{Valore} & \textbf{Significato} \\
+ \textbf{\param{mode}} & \textbf{Valore} & \textbf{Significato} \\
\hline
\hline
- \macro{S\_ISUID} & 04000 & set user ID \\
- \macro{S\_ISGID} & 02000 & set group ID \\
- \macro{S\_ISVTX} & 01000 & sticky bit \\
+ \const{S\_ISUID} & 04000 & set user ID \\
+ \const{S\_ISGID} & 02000 & set group ID \\
+ \const{S\_ISVTX} & 01000 & sticky bit \\
\hline
- \macro{S\_IRWXU} & 00700 & l'utente ha tutti i permessi \\
- \macro{S\_IRUSR} & 00400 & l'utente ha il permesso di lettura \\
- \macro{S\_IWUSR} & 00200 & l'utente ha il permesso di scrittura \\
- \macro{S\_IXUSR} & 00100 & l'utente ha il permesso di esecuzione \\
+ \const{S\_IRWXU} & 00700 & l'utente ha tutti i permessi \\
+ \const{S\_IRUSR} & 00400 & l'utente ha il permesso di lettura \\
+ \const{S\_IWUSR} & 00200 & l'utente ha il permesso di scrittura \\
+ \const{S\_IXUSR} & 00100 & l'utente ha il permesso di esecuzione \\
\hline
- \macro{S\_IRWXG} & 00070 & il gruppo ha tutti i permessi \\
- \macro{S\_IRGRP} & 00040 & il gruppo ha il permesso di lettura \\
- \macro{S\_IWGRP} & 00020 & il gruppo ha il permesso di scrittura \\
- \macro{S\_IXGRP} & 00010 & il gruppo ha il permesso di esecuzione \\
+ \const{S\_IRWXG} & 00070 & il gruppo ha tutti i permessi \\
+ \const{S\_IRGRP} & 00040 & il gruppo ha il permesso di lettura \\
+ \const{S\_IWGRP} & 00020 & il gruppo ha il permesso di scrittura \\
+ \const{S\_IXGRP} & 00010 & il gruppo ha il permesso di esecuzione \\
\hline
- \macro{S\_IRWXO} & 00007 & gli altri hanno tutti i permessi \\
- \macro{S\_IROTH} & 00004 & gli altri hanno il permesso di lettura \\
- \macro{S\_IWOTH} & 00002 & gli altri hanno il permesso di scrittura \\
- \macro{S\_IXOTH} & 00001 & gli altri hanno il permesso di esecuzione \\
+ \const{S\_IRWXO} & 00007 & gli altri hanno tutti i permessi \\
+ \const{S\_IROTH} & 00004 & gli altri hanno il permesso di lettura \\
+ \const{S\_IWOTH} & 00002 & gli altri hanno il permesso di scrittura \\
+ \const{S\_IXOTH} & 00001 & gli altri hanno il permesso di esecuzione \\
\hline
\end{tabular}
- \caption{I valori delle costanti usate per indicare i permessi dei file.}
+ \caption{Valori delle costanti usate per indicare i vari bit di
+ \param{mode} utilizzato per impostare i permessi dei file.}
\label{tab:file_permission_const}
\end{table}
-Il cambiamento dei permessi di un file attraverso queste funzioni ha comunque
-alcune limitazioni, provviste per motivi di sicurezza. Questo significa che
-anche se si è proprietari del file non tutte le operazioni sono permesse, in
-particolare:
+Le costanti con cui specificare i singoli bit di \param{mode} sono riportate
+in tab.~\ref{tab:file_permission_const}. Il valore di \param{mode} può essere
+ottenuto combinando fra loro con un OR binario le costanti simboliche relative
+ai vari bit, o specificato direttamente, come per l'omonimo comando di shell,
+con un valore numerico (la shell lo vuole in ottale, dato che i bit dei
+permessi sono divisibili in gruppi di tre), che si può calcolare direttamente
+usando lo schema si utilizzo dei bit illustrato in
+fig.~\ref{fig:file_perm_bit}.
+
+Ad esempio i permessi standard assegnati ai nuovi file (lettura e scrittura
+per il proprietario, sola lettura per il gruppo e gli altri) sono
+corrispondenti al valore ottale $0644$, un programma invece avrebbe anche il
+bit di esecuzione attivo, con un valore di $0755$, se si volesse attivare il
+bit \acr{suid} il valore da fornire sarebbe $4755$.
+
+Il cambiamento dei permessi di un file eseguito attraverso queste funzioni ha
+comunque alcune limitazioni, previste per motivi di sicurezza. L'uso delle
+funzioni infatti è possibile solo se l'user-ID effettivo del processo
+corrisponde a quello del proprietario del file o dell'amministratore,
+altrimenti esse falliranno con un errore di \errcode{EPERM}.
+
+Ma oltre a questa regola generale, di immediata comprensione, esistono delle
+limitazioni ulteriori. Per questo motivo, anche se si è proprietari del file,
+non tutti i valori possibili di \param{mode} sono permessi o hanno effetto;
+in particolare accade che:
\begin{enumerate}
\item siccome solo l'amministratore può impostare lo \textit{sticky bit}, se
- l'userid effettivo del processo non è zero esso viene automaticamente
+ l'user-ID effettivo del processo non è zero esso viene automaticamente
cancellato (senza notifica di errore) qualora sia stato indicato in
- \var{mode}.
-\item per via della semantica SVr4 nella creazione dei nuovi file, si può
- avere il caso in cui il file creato da un processo è assegnato a un gruppo
- per il quale il processo non ha privilegi. Per evitare che si possa
- assegnare il bit \acr{sgid} ad un file appartenente a un gruppo per cui non
- si hanno diritti, questo viene automaticamente cancellato (senza notifica di
- errore) da \var{mode} qualora il gruppo del file non corrisponda a quelli
- associati al processo (la cosa non avviene quando l'userid effettivo del
- processo è zero).
+ \param{mode}.
+\item per quanto detto in sez.~\ref{sec:file_ownership} riguardo la creazione
+ dei nuovi file, si può avere il caso in cui il file creato da un processo è
+ assegnato a un gruppo per il quale il processo non ha privilegi. Per evitare
+ che si possa assegnare il bit \acr{sgid} ad un file appartenente a un gruppo
+ per cui non si hanno diritti, questo viene automaticamente cancellato da
+ \param{mode} (senza notifica di errore) qualora il gruppo del file non
+ corrisponda a quelli associati al processo (la cosa non avviene quando
+ l'user-ID effettivo del processo è zero).
\end{enumerate}
Per alcuni filesystem\footnote{il filesystem \acr{ext2} supporta questa
caratteristica, che è mutuata da BSD.} è inoltre prevista una ulteriore
misura di sicurezza, volta a scongiurare l'abuso dei bit \acr{suid} e
-\acr{sgid}; essa consiste nel cancellare automaticamente questi bit qualora un
-processo che non appartenga all'amministratore scriva su un file. In questo
-modo anche se un utente malizioso scopre un file \acr{suid} su cui può
-scrivere, un'eventuale modifica comporterà la perdita di ogni ulteriore
-privilegio.
+\acr{sgid}; essa consiste nel cancellare automaticamente questi bit dai
+permessi di un file qualora un processo che non appartenga all'amministratore
+effettui una scrittura. In questo modo anche se un utente malizioso scopre un
+file \acr{suid} su cui può scrivere, un'eventuale modifica comporterà la
+perdita di questo privilegio.
\subsection{La funzione \func{umask}}
\label{sec:file_umask}
-Oltre che dai valori indicati in sede di creazione, i permessi assegnati ai
-nuovi file sono controllati anche da una maschera di bit impostata con la
-funzione \func{umask}, il cui prototipo è:
+Le funzioni \func{chmod} e \func{fchmod} ci permettono di modificare i
+permessi di un file, resta però il problema di quali sono i permessi assegnati
+quando il file viene creato. Le funzioni dell'interfaccia nativa di Unix, come
+vedremo in sez.~\ref{sec:file_open}, permettono di indicare esplicitamente i
+permessi di creazione di un file, ma questo non è possibile per le funzioni
+dell'interfaccia standard ANSI C che non prevede l'esistenza di utenti e
+gruppi, ed inoltre il problema si pone anche per l'interfaccia nativa quando i
+permessi non vengono indicati esplicitamente.
+
+In tutti questi casi l'unico riferimento possibile è quello della modalità di
+apertura del nuovo file (lettura/scrittura o sola lettura), che però può
+fornire un valore che è lo stesso per tutti e tre i permessi di
+sez.~\ref{sec:file_perm_overview} (cioè $666$ nel primo caso e $222$ nel
+secondo). Per questo motivo il sistema associa ad ogni processo\footnote{è
+ infatti contenuta nel campo \var{umask} della struttura \struct{fs\_struct},
+ vedi fig.~\ref{fig:proc_task_struct}.} una maschera di bit, la cosiddetta
+\textit{umask}, che viene utilizzata per impedire che alcuni permessi possano
+essere assegnati ai nuovi file in sede di creazione. I bit indicati nella
+maschera vengono infatti cancellati dai permessi quando un nuovo file viene
+creato.
+
+La funzione che permette di impostare il valore di questa maschera di
+controllo è \funcd{umask}, ed il suo prototipo è:
\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
- \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
-creato.
-
-In genere questa maschera serve per impostare un valore predefinito dei
-permessi che ne escluda alcuni (usualmente quello di scrittura per il gruppo e
-gli altri, corrispondente ad un valore di $022$). Essa è utile perché le
-routine dell'interfaccia ANSI C degli stream non prevedono l'esistenza dei
-permessi, e pertanto tutti i nuovi file vengono sempre creati con un valore di
-$666$ (cioè permessi di lettura e scrittura per tutti, si veda
-\tabref{tab:file_permission_const} per un confronto); in questo modo è
-possibile cancellare automaticamente i permessi non voluti, senza doverlo fare
-esplicitamente.
-
-In genere il valore di \func{umask} viene stabilito una volta per tutte al
-login a $022$, e di norma gli utenti non hanno motivi per modificarlo. Se però
-si vuole che un processo possa creare un file che chiunque possa leggere
-allora occorrerà cambiare il valore di \func{umask}.
+In genere si usa questa maschera per impostare un valore predefinito che
+escluda preventivamente alcuni permessi (usualmente quello di scrittura per il
+gruppo e gli altri, corrispondente ad un valore per \param{mask} pari a
+$022$). In questo modo è possibile cancellare automaticamente i permessi non
+voluti. Di norma questo valore viene impostato una volta per tutte al login a
+$022$, e gli utenti non hanno motivi per modificarlo.
\subsection{Le funzioni \func{chown}, \func{fchown} e \func{lchown}}
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:
\begin{errlist}
- \item[\macro{EPERM}] L'userid effettivo non corrisponde a quello del
+ \item[\errcode{EPERM}] L'user-ID effettivo non corrisponde a quello del
proprietario del file o non è zero, o utente e gruppo non sono validi
\end{errlist}
- Oltre a questi entrambe restituiscono gli errori \macro{EROFS} e
- \macro{EIO}; \func{chown} restituisce anche \macro{EFAULT},
- \macro{ENAMETOOLONG}, \macro{ENOENT}, \macro{ENOMEM}, \macro{ENOTDIR},
- \macro{EACCES}, \macro{ELOOP}; \func{fchown} anche \macro{EBADF}.}
+ Oltre a questi entrambe restituiscono gli errori \errval{EROFS} e
+ \errval{EIO}; \func{chown} restituisce anche \errval{EFAULT},
+ \errval{ENAMETOOLONG}, \errval{ENOENT}, \errval{ENOMEM}, \errval{ENOTDIR},
+ \errval{EACCES}, \errval{ELOOP}; \func{fchown} anche \errval{EBADF}.}
\end{functions}
In Linux soltanto l'amministratore può cambiare il proprietario di un file,
\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
%La struttura fondamentale che contiene i dati essenziali relativi ai file è il
%cosiddetto \textit{inode}; questo conterrà informazioni come il
%tipo di file (file di dispositivo, directory, file di dati, per un elenco
-%completo vedi \ntab), i permessi (vedi \secref{sec:file_perms}), le date (vedi
-%\secref{sec:file_times}).
+%completo vedi \ntab), i permessi (vedi sez.~\ref{sec:file_perms}), le date (vedi
+%sez.~\ref{sec:file_times}).
+
+
+\subsection{Un quadro d'insieme sui permessi}
+\label{sec:file_riepilogo}
+
+Avendo affrontato in maniera separata il comportamento delle varie funzioni ed
+il significato dei singoli bit dei permessi sui file, vale la pena fare un
+riepilogo in cui si riassumono le caratteristiche di ciascuno di essi, in modo
+da poter fornire un quadro d'insieme.
+
+In tab.~\ref{tab:file_fileperm_bits} si sono riassunti gli effetti dei vari
+bit per un file; per quanto riguarda l'applicazione dei permessi per
+proprietario, gruppo ed altri si ricordi quanto illustrato in
+sez.~\ref{sec:file_perm_overview}. Si rammenti che il valore dei permessi non
+ha alcun effetto qualora il processo possieda i privilegi di amministratore.
+
+\begin{table}[!htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|c|c|c|c|c|c|c|c|c|c|c|c|l|}
+ \hline
+ \multicolumn{3}{|c|}{}&
+ \multicolumn{3}{|c|}{user}&
+ \multicolumn{3}{|c|}{group}&
+ \multicolumn{3}{|c|}{other}&
+ \multirow{2}{*}{\textbf{Operazioni possibili}} \\
+ \cline{1-12}
+ \acr{s}&\acr{s}&\acr{t}&r&w&x&r&w&x&r&w&x& \\
+ \hline
+ \hline
+ 1&-&-&-&-&-&-&-&-&-&-&-&Se eseguito ha i permessi del proprietario\\
+ -&1&-&-&-&1&-&-&-&-&-&-&Se eseguito ha i permessi del gruppo proprietario\\
+ -&1&-&-&-&0&-&-&-&-&-&-&Il \textit{mandatory locking} è abilitato\\
+ -&-&1&-&-&-&-&-&-&-&-&-&Non utilizzato\\
+ -&-&-&1&-&-&-&-&-&-&-&-&Permesso di lettura per il proprietario\\
+ -&-&-&-&1&-&-&-&-&-&-&-&Permesso di scrittura per il proprietario\\
+ -&-&-&-&-&1&-&-&-&-&-&-&Permesso di esecuzione per il proprietario\\
+ -&-&-&-&-&-&1&-&-&-&-&-&Permesso di lettura per il gruppo proprietario\\
+ -&-&-&-&-&-&-&1&-&-&-&-&Permesso di scrittura per il gruppo proprietario\\
+ -&-&-&-&-&-&-&-&1&-&-&-&Permesso di esecuzione per il gruppo proprietario\\
+ -&-&-&-&-&-&-&-&-&1&-&-&Permesso di lettura per tutti gli altri\\
+ -&-&-&-&-&-&-&-&-&-&1&-&Permesso di scrittura per tutti gli altri \\
+ -&-&-&-&-&-&-&-&-&-&-&1&Permesso di esecuzione per tutti gli altri\\
+ \hline
+ \end{tabular}
+ \caption{Tabella riassuntiva del significato dei bit dei permessi per un
+ file.}
+ \label{tab:file_fileperm_bits}
+\end{table}
+
+Per compattezza, nella tabella si sono specificati i bit di \acr{suid},
+\acr{sgid} e \acr{sticky} con la notazione illustrata anche in
+fig.~\ref{fig:file_perm_bit}.
+
+In tab.~\ref{tab:file_dirperm_bits} si sono invece riassunti gli effetti dei
+vari bit dei permessi per una directory; anche in questo caso si sono
+specificati i bit di \acr{suid}, \acr{sgid} e \acr{sticky} con la notazione
+compatta illustrata in fig.~\ref{fig:file_perm_bit}.
+
+\begin{table}[!htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|c|c|c|c|c|c|c|c|c|c|c|c|l|}
+ \hline
+ \multicolumn{3}{|c|}{}&
+ \multicolumn{3}{|c|}{user}&
+ \multicolumn{3}{|c|}{group}&
+ \multicolumn{3}{|c|}{other}&
+ \multirow{2}{*}{\textbf{Operazioni possibili}} \\
+ \cline{1-12}
+ \acr{s}&\acr{s}&\acr{t}&r&w&x&r&w&x&r&w&x& \\
+ \hline
+ \hline
+ 1&-&-&-&-&-&-&-&-&-&-&-&Non utilizzato\\
+ -&1&-&-&-&-&-&-&-&-&-&-&Propaga il gruppo proprietario ai nuovi file creati\\
+ -&-&1&-&-&-&-&-&-&-&-&-&Limita l'accesso in scrittura dei file nella directory\\
+ -&-&-&1&-&-&-&-&-&-&-&-&Permesso di visualizzazione per il proprietario\\
+ -&-&-&-&1&-&-&-&-&-&-&-&Permesso di aggiornamento per il proprietario\\
+ -&-&-&-&-&1&-&-&-&-&-&-&Permesso di attraversamento per il proprietario\\
+ -&-&-&-&-&-&1&-&-&-&-&-&Permesso di visualizzazione per il gruppo proprietario\\
+ -&-&-&-&-&-&-&1&-&-&-&-&Permesso di aggiornamento per il gruppo proprietario\\
+ -&-&-&-&-&-&-&-&1&-&-&-&Permesso di attraversamento per il gruppo proprietario\\
+ -&-&-&-&-&-&-&-&-&1&-&-&Permesso di visualizzazione per tutti gli altri\\
+ -&-&-&-&-&-&-&-&-&-&1&-&Permesso di aggiornamento per tutti gli altri \\
+ -&-&-&-&-&-&-&-&-&-&-&1&Permesso di attraversamento per tutti gli altri\\
+ \hline
+ \end{tabular}
+ \caption{Tabella riassuntiva del significato dei bit dei permessi per una
+ directory.}
+ \label{tab:file_dirperm_bits}
+\end{table}
+
+Nelle tabelle si è indicato con ``-'' il fatto che il valore degli altri bit
+non è influente rispetto a quanto indicato in ciascuna riga; l'operazione fa
+riferimento soltanto alla combinazione di bit per i quali il valore è
+riportato esplicitamente.
+
\subsection{La funzione \func{chroot}}
\label{sec:file_chroot}
-Benché non abbia niente a che fare con permessi, utenti e gruppi, questa
-funzione viene usata spesso per restringere le capacità di acccesso di un
+Benché non abbia niente a che fare con permessi, utenti e gruppi, la funzione
+\func{chroot} viene usata spesso per restringere le capacità di accesso 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,\footnote{entrambe sono
- contenute in due campi di \var{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
-\secref{sec:file_organization}). La radice viene eredidata dal padre per ogni
-processo figlio, 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 è:
+Come accennato in sez.~\ref{sec:proc_fork} ogni processo oltre ad una
+directory di lavoro, ha anche una directory \textsl{radice}\footnote{entrambe
+ sono contenute in due campi (rispettivamente \var{pwd} e \var{root}) di
+ \struct{fs\_struct}; vedi fig.~\ref{fig:proc_task_struct}.} che, pur essendo
+di norma corrispondente alla radice dell'albero di file e directory come visto
+dal kernel (ed illustrato in sez.~\ref{sec:file_organization}), ha per il
+processo il significato specifico di directory rispetto alla quale vengono
+risolti i \index{\textit{pathname}!assoluto}\textit{pathname}
+assoluti.\footnote{cioè quando un processo chiede la risoluzione di un
+ \textit{pathname}, il kernel usa sempre questa directory come punto di
+ partenza.} Il fatto che questo valore sia specificato per ogni processo apre
+allora la possibilità di modificare le modalità di risoluzione dei
+\textit{pathname} assoluti da parte di un processo cambiando questa directory,
+così come si fa coi \index{\textit{pathname}!relativo}\textit{pathname}
+relativi cambiando la directory di lavoro.
+
+Normalmente la directory radice di un processo coincide anche con la radice
+del filesystem usata dal kernel, e dato che il suo valore viene ereditato dal
+padre da ogni processo figlio, in generale i processi risolvono i
+\index{\textit{pathname}!assoluto}\textit{pathname} assoluti a partire sempre
+dalla stessa directory, che corrisponde alla \file{/} del sistema.
+
+In certe situazioni però, per motivi di sicurezza, è utile poter impedire che
+un processo possa accedere a tutto il filesystem; per far questo si può
+cambiare la sua directory radice con la funzione \funcd{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} può assumere i valori:
\begin{errlist}
- \item[\macro{EPERM}] L'userid effettivo del processo non è zero.
+ \item[\errcode{EPERM}] L'user-ID effettivo del processo 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}.}
+ ed inoltre \errval{EFAULT}, \errval{ENAMETOOLONG}, \errval{ENOENT},
+ \errval{ENOMEM}, \errval{ENOTDIR}, \errval{EACCES}, \errval{ELOOP};
+ \errval{EROFS} e \errval{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}.
+\param{path} (che ovviamente deve esistere) ed ogni
+\index{\textit{pathname}!assoluto}\textit{pathname} assoluto usato dalle
+funzioni chiamate nel processo sarà risolto a partire da essa, rendendo
+impossibile accedere alla parte di albero sovrastante. Si ha così quella che
+viene chiamata una \textit{chroot jail}, in quanto il processo non può più
+accedere a file al di fuori della sezione di albero in cui è stato
+\textsl{imprigionato}.
+
+Solo un processo con i privilegi di amministratore può usare questa funzione,
+e la nuova radice, per quanto detto in sez.~\ref{sec:proc_fork}, sarà ereditata
+da tutti i suoi processi figli. Si tenga presente però che la funzione non
+cambia la directory di lavoro, che potrebbe restare fuori dalla \textit{chroot
+ jail}.
Questo è il motivo per cui la funzione è efficace solo se dopo averla eseguita
-si cedono i privilegi di root. Infatti se in qualche modo il processo ha una
-directory di lavoro corrente fuori dalla \textit{chroot jail}, potrà comunque
-accedere a tutto il filesystem usando pathname relativi.
-
-Ma quando ad un processo restano i privilegi di root esso potrà sempre portare
-la directory di lavoro corrente fuori dalla \textit{chroot jail} creando una
-sottodirectory ed eseguendo una \func{chroot} su di essa. Per questo motivo
-l'uso di questa funzione non ha molto senso quando un processo necessita dei
-privilegi di root per le sue normali operazioni.
-
-Un caso tipico di uso di \func{chroot} è quello di un server ftp anonimo, in
+si cedono i privilegi di root. Infatti se per un qualche motivo il processo
+resta con la directory di lavoro fuori dalla \textit{chroot jail}, potrà
+comunque accedere a tutto il resto del filesystem usando
+\index{\textit{pathname}!relativo}\textit{pathname} relativi, i quali,
+partendo dalla directory di lavoro che è fuori della \textit{chroot jail},
+potranno (con l'uso di \texttt{..}) risalire fino alla radice effettiva del
+filesystem.
+
+Ma se ad un processo restano i privilegi di amministratore esso potrà comunque
+portare la sua directory di lavoro fuori dalla \textit{chroot jail} in cui si
+trova. Basta infatti creare una nuova \textit{chroot jail} con l'uso di
+\func{chroot} su una qualunque directory contenuta nell'attuale directory di
+lavoro. Per questo motivo l'uso di questa funzione non ha molto senso quando
+un processo necessita dei privilegi di root per le sue normali operazioni.
+
+Un caso tipico di uso di \func{chroot} è quello di un server FTP anonimo, 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à