-\section{La manipolazione di file e directory}
+\section{La gestione di file e directory}
Come già accennato in \secref{sec:file_filesystem} in un sistema unix-like la
gestione dei file ha delle caratteristiche specifiche che derivano
direttamente dall'architettura del sistema; in questa sezione esamineremo le
funzioni usate per manipolazione nel filesytem di file e directory, per la
creazione di link simbolici e diretti, per la gestione e la lettura delle
-directory; mettendo in evidenza le conseguenze della struttura standard della
-gestione dei file in un sistema unix-like, già accennate al capitolo
-precedente.
+directory; il tutto mettendo in evidenza le conseguenze della struttura
+standard della gestione dei file in un sistema unix-like, già accennate al
+capitolo precedente.
\subsection{Le funzioni \func{link} e \func{unlink}}
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 riferiremento allo stesso file, chiamandolo con nomi
-diversi o accedendovi da directory diverse.
+permettono di fare riferiremento 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
+usualmente chiamati \textit{link}; ma data la struttura del sistema di
gestione dei file (ed in particolare quanto trattato in
\secref{sec:file_architecture}) ci sono due metodi sostanzialmente diversi per
fare questa operazione.
una directory è solo una etichetta associata ad un puntatore a che fa
riferimento al suddetto inode.
-
Questo significa che la realizzazione di un link è immediata in quanto uno
stesso file può avere tanti nomi diversi allo stesso tempo, dati da
altrettante diverse associazioni allo stesso inode; si noti poi che nessuno di
Windows).
La funzione inoltre opera sia sui file ordinari che sugli altri oggetti del
-filesystem, con l'eccezione delle directory. In alcuni sistemi solo
+filesystem, con l'eccezione delle directory. In alcuni 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
non sono in grado di gestire e la cui rimozione diventerebbe estremamente
-complicata (in genere occorre far girare il programma \cmd{fsck} per riparare
-il filesystem).
+complicata (in genere per questo tipo di errori occorre far girare il
+programma \cmd{fsck} per riparare il filesystem).
Data la pericolosità di questa operazione e la disponibilità dei link
simbolici che possono fornire la stessa funzionalità senza questi problemi,
\end{errlist}
ed inoltre: \macro{EACCES}, \macro{EFAULT}, \macro{ENOENT}, \macro{ENOTDIR},
\macro{ENOMEM}, \macro{EROFS}, \macro{ELOOP}, \macro{EIO}.
-
\end{prototype}
Per cancellare una voce in una directory è necessario avere il permesso di
\label{sec:file_remove}
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
+\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
riportato nelle descrizioni di \func{unlink} e \func{rmdir}.
\end{prototype}
-Per cambiare nome ad un file (o a una directory) 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 è:
+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 è:
\begin{prototype}{stdio.h}
-{int rename(const char *oldpath, const char *newpath)}
- Rinomina un file, spostandolo fra directory diverse quando richiesto.
+ {int rename(const char *oldpath, const char *newpath)}
+
+ Rinomina \var{oldpath} in \var{newpth}, eseguendo se necessario lo
+ spostamento di un file fra directory diverse. Eventuali altri link diretti
+ allo stesso file non vengono influenzati.
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 settata
\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 root) o del sistema
+ 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
\macro{ELOOP} e \macro{ENOSPC}.
\end{prototype}
-
-il vantaggio nell'uso
-di questa funzione al posto della chiamata successiva di \func{link} e
-\func{unlink} è che l'operazione è eseguita atomicamente, e non c'è un momento
-in cui il file su disco presenta ad un altro processo un diverso numero di
-collegamenti diretti. Inoltre in questo modo non c'è modo che il nuovo nome
-esista senza essere connesso all'inode; se si ha un crollo del sistema durante
-l'esecuzione può essere possibile che entrambi i nomi esistano, ma il nuovo
-nome quando esiste, è sempre connesso al file.
-
-
-L'effetto è diverso a seconda che si voglia spostare un file o una directory;
-se ci riferisce a un file allora \var{newpath} deve essere una di
-
+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
+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}.
+
+Se \var{oldpath} si riferisce a un link simbolico questo sara 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 glibc, il comportamento più ragionevole sarebbe
+quello di cancellare \var{oldpath}.
+
+Il vantaggio nell'uso di questa funzione al posto della chiamata successiva di
+\func{link} e \func{unlink} è che l'operazione è eseguita atomicamente, non
+può esistere cioè nessun istante in cui un altro processo può trovare attivi
+entrambi i nomi dello stesso file, o, in caso di sostituzione di un file
+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
+motivo (come un crash del kernel), \func{rename} garantisce di lasciare
+presente una istanza di \var{newpath}, tuttavia nella sovrascrittura potrà
+esistere una finestra in cui sia \var{oldpath} che \var{newpath} fanno
+riferimento allo stesso file.
\subsection{I link simbolici}
\label{sec:file_symlink}
\end{errlist}
\end{prototype}
-Dato che la funzione \func{open} segue i link simbolici, è necessaria usare
-un'altra funzione quando si vuole leggere il contenuto di un link simbolico,
-questa funzione è la:
+Dato che, come indicato in \secref{tab:file_symb_effect}, la funzione
+\func{open} segue i link simbolici, è necessaria usare un'altra funzione
+quando si vuole leggere il contenuto di un link simbolico, questa funzione è
+la:
\begin{prototype}{unistd.h}
{int readlink(const char * path, char * buff, size\_t size)}
\begin{prototype}{unistd.h}{int chdir (const char * pathname)}
Come dice il nome (che significa \textit{change directory}) questa funzione
serve a cambiare la directory di lavoro a quella specificata dal pathname
- contenuto nella stringa \texttt{pathname}.
+ contenuto nella stringa \var{pathname}.
\end{prototype}
\begin{prototype}{unistd.h}{int fchdir (int filedes)}
di \cmd{ls}.
Se è sempre possibile allargare un file scrivendoci sopra od usando la
-funzione \func{seek} per spostarsi oltre la sua fine. Esistono però anche casi
-in cui si può avere bisogno di effettuare un troncamento scartando i dati al
-di là della dimensione scelta come nuova fine del file.
+funzione \func{seek} (vedi \secref{sec:file_seek}) per spostarsi oltre la sua
+fine. Esistono però anche casi in cui si può avere bisogno di effettuare un
+troncamento scartando i dati al di là della dimensione scelta come nuova fine
+del file.
Un file può essere troncato a zero aprendolo con il flag \macro{O\_TRUNC}, ma
questo è un caso particolare; per qualunque altra dimensione si possono usare
\func{ftruncate} si hanno i valori:
\begin{errlist}
\item \macro{EBADF} \var{fd} non è un file descriptor.
- \item \texttt{EINVAL} \var{fd} è un riferimento ad un socket, non a un file
+ \item \macro{EINVAL} \var{fd} è un riferimento ad un socket, non a un file
o non è aperto in scrittura.
\end{errlist}
per \func{truncate} si hanno:
\begin{errlist}
- \item \texttt{EACCES} il file non ha permesso di scrittura o non si ha il
+ \item \macro{EACCES} il file non ha permesso di scrittura o non si ha il
permesso di esecuzione una delle directory del pathname.
- \item \texttt{ETXTBSY} Il file è un programma in esecuzione.
+ \item \macro{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}.
\end{lstlisting}
L'effetto della funzione e i privilegi necessari per eseguirla dipendono da
-cosa è l'argomento \var{times}; se è \textit{NULL} la funzione setta il tempo
+cosa è l'argomento \var{times}; se è \macro{NULL} la funzione setta il tempo
corrente ed è sufficiente avere accesso in scrittura al file; se invece si è
specificato un valore la funzione avrà successo solo se si è proprietari del
file (o si hanno i privilegi di amministratore).
stesso problema di presenta per la creazione di nuove directory (procedimento
descritto in \secref{sec:file_dir_creat_rem}).
-Lo standard POSIX prescrive che l'uid del nuovo file corrisponda
+Lo standard POSIX prescrive che l'\acr{uid} del nuovo file corrisponda
all'\textit{effective user id} del processo che lo crea; per il \acr{gid}
invece prevede due diverse possibilità:
\begin{itemize}
semantica BSD. Linux invece segue quella che viene chiamata semantica SVR4; di
norma cioè il nuovo file viene creato, seguendo la prima opzione, con il
\acr{gid} del processo, se però la directory in cui viene creato il file ha il
-bit \acr{sgid} settato allora viene usata la seconda opzione..
+bit \acr{sgid} settato allora viene usata la seconda opzione.
Usare la semantica BSD ha il vantaggio che il \acr{gid} viene sempre
automaticamente propagato, restando coerente a quello della directory di
un file viene fatto usando \textit{effective user id} e \textit{effective
group id} del processo, ma ci sono casi in cui si può voler effettuare il
controllo usando il \textit{real user id} e il \textit{real group id} (cioè
-l'uid dell'utente che ha lanciato il programma, che, come accennato in
+l'\acr{uid} dell'utente che ha lanciato il programma, che, come accennato in
\secref{sec:file_suid_sgid} e spiegato in \secref{sec:proc_perms} non è
detto sia uguale all'\textit{effective user id}). Per far questo si può usare
la funzione \func{access}, il cui prototipo è:
file indicato da \var{pathname}.
La funzione ritorna 0 se l'accesso è consentito, -1 altrimenti; in
- quest'ultimo caso la variabile \texttt{errno} viene settata secondo i codici
+ quest'ultimo caso la variabile \var{errno} viene settata secondo i codici
di errore: \macro{EACCES}, \macro{EROFS}, \macro{EFAULT}, \macro{EINVAL},
\macro{ENAMETOOLONG}, \macro{ENOENT}, \macro{ENOTDIR}, \macro{ELOOP},
\macro{EIO}.
\end{prototype}
-
I valori possibili per il parametro \var{mode} sono esprimibili come
combinazione delle costanti numeriche riportate in \ntab\ (attraverso un OR
binario). I primi tre valori implicano anche la verifica dell'esistenza del
Un esempio tipico per l'uso di questa funzione è quello di un processo che sta
eseguendo un programma coi privilegi di un altro utente (attraverso l'uso del
-suid bit) che vuole controllare se l'utente originale ha i permessi per
+\acr{suid} bit) che vuole controllare se l'utente originale ha i permessi per
accedere ad un certo file.
-\subsection{Le funzioni \texttt{chmod} e \texttt{fchmod}}
+\subsection{Le funzioni \func{chmod} e \func{fchmod}}
\label{sec:file_chmod}
Per cambiare i permessi di un file il sistema mette ad disposizione due
funzioni, che operano rispettivamente su un filename e su un file descriptor,
-i cui prototipi sono:
+i loro prototipi sono:
\begin{functions}
\headdecl{sys/types.h}
il file descriptor \var{fd} per indicare il file.
Le funzioni restituiscono zero in caso di successo e -1 per un errore, in
- caso di errore \texttt{errno} può assumere i valori:
+ caso di errore \var{errno} può assumere i valori:
\begin{errlist}
\item \macro{EPERM} L'\textit{effective user id} non corrisponde a quello
del proprietario del file o non è zero.
\end{functions}
I valori possibili per \var{mode} sono indicati in \ntab. I valori possono
-esser combinati con l'OR binario delle relative macro, o specificati
-direttamente, come per l'analogo comando di shell, con il valore ottale. 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 suid
-il valore da fornire sarebbe $4755$.
+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 suid il valore da fornire sarebbe $4755$.
\begin{table}[!htb]
\centering
anche se si è proprietari del file non tutte le operazioni sono permesse, in
particolare:
\begin{itemize}
-\item siccome solo l'amministratore può settare lo \textit{sticky bit} se se
+\item siccome solo l'amministratore può settare lo \textit{sticky bit}; se
l'\textit{effective user id} del processo non è zero esso viene
automaticamente cancellato (senza notifica di errore) qualora sia stato
indicato in \var{mode}.