%% filedir.tex
%%
-%% Copyright (C) 2000-2002 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2003 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 "Prefazione",
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 è
-\funcd{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
+ \tabref{tab:file_file_types}, contrassegnato come tale nell'inode, e
+ riconoscibile dal valore del campo \var{st\_mode} della struttura
+ \struct{stat} (vedi \secref{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 è
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
- \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
-struct dirent {
- ino_t d_ino; /* inode number */
- off_t d_off; /* offset to the next dirent */
- unsigned short int d_reclen; /* length of this record */
- unsigned char d_type; /* type of file */
- char d_name[256]; /* We must not include limits.h! */
-};
- \end{lstlisting}
+ \includestruct{listati/dirent.c}
\end{minipage}
\normalsize
\caption{La struttura \structd{dirent} per la lettura delle informazioni dei
\cmd{ls}).
\begin{figure}[!htb]
- \footnotesize
- \begin{lstlisting}{}
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h> /* directory */
-#include <stdlib.h> /* C standard library */
-#include <unistd.h>
-
-/* computation function for DirScan */
-int do_ls(struct dirent * direntry);
-/* main body */
-int main(int argc, char *argv[])
-{
- ...
- if ((argc - optind) != 1) { /* There must be remaing parameters */
- printf("Wrong number of arguments %d\n", argc - optind);
- usage();
- }
- DirScan(argv[1], do_ls);
- exit(0);
-}
-/*
- * Routine to print file name and size inside DirScan
- */
-int do_ls(struct dirent * direntry)
-{
- struct stat data;
-
- stat(direntry->d_name, &data); /* get stat data */
- printf("File: %s \t size: %d\n", direntry->d_name, data.st_size);
- return 0;
-}
- \end{lstlisting}
+ \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}
valore di ritorno per indicare una esecuzione senza errori.
\begin{figure}[!htb]
- \footnotesize
- \begin{lstlisting}{}
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h> /* directory */
-#include <stdlib.h> /* C standard library */
-#include <unistd.h>
-
-/*
- * Function DirScan:
- *
- * Input: the directory name and a computation function
- * Return: 0 if OK, -1 on errors
- */
-int DirScan(char * dirname, int(*compute)(struct dirent *))
-{
- DIR * dir;
- struct dirent *direntry;
-
- if ( (dir = opendir(dirname)) == NULL) { /* oper directory */
- printf("Opening %s\n", dirname); /* on error print messages */
- perror("Cannot open directory"); /* and then return */
- return -1;
- }
- fd = dirfd(dir); /* get file descriptor */
- fchdir(fd); /* change directory */
- /* loop on directory entries */
- while ( (direntry = readdir(dir)) != NULL) { /* read entry */
- if (compute(direntry)) { /* execute function on it */
- return -1; /* on error return */
- }
- }
- closedir(dir);
- return 0;
-}
-
- \end{lstlisting}
+ \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}
\label{sec:file_work_dir}
A ciascun processo è associata 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 pathname è espresso in forma
-relativa, dove il ``\textsl{relativa}'' fa riferimento appunto a questa
-directory.
+\textsl{directory corrente} o \textsl{directory di lavoro} (in inglese
+\textit{current working directory}) che è quella a cui si fa riferimento
+quando un 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
\textit{home directory} del suo account. Il comando \cmd{cd} della shell
directory corrente di qualunque comando da essa lanciato.
In genere il kernel tiene traccia per ciascun processo dell'inode\index{inode}
-della directory di lavoro corrente, per ottenere il pathname occorre usare una
-apposita funzione di libreria, \funcd{getcwd}, il cui prototipo è:
+della directory di lavoro, per ottenere il pathname occorre usare una apposita
+funzione di libreria, \funcd{getcwd}, il cui prototipo è:
\begin{prototype}{unistd.h}{char *getcwd(char *buffer, size\_t size)}
Legge il pathname della directory di lavoro corrente.
\end{errlist}}
\end{prototype}
-La funzione restituisce il pathname completo della directory di lavoro
-corrente 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 pathname
-completo più lo zero di terminazione della stringa. Qualora esso ecceda le
-dimensioni specificate con \param{size} la funzione restituisce un errore.
+La funzione restituisce il 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 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,
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
-\funcd{chdir} (equivalente del comando di shell \cmd{cd}) il cui nome sta
-appunto per \textit{change directory}, il suo prototipo è:
+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:
funzione non si può usare una stringa costante. Tutte le avvertenze riguardo
alle possibili \textit{race condition}\index{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, \funcd{mkstemp} è sostanzialmente equivalente a
\func{tmpfile}, ma restituisce un file descriptor invece di uno stream; il suo
\funcdecl{int lstat(const char *file\_name, struct stat *buf)} Identica a
\func{stat} eccetto che se il \param{file\_name} è un link simbolico vengono
- lette le informazioni relativa ad esso e non al file a cui fa riferimento.
+ 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
\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 \structd{stat} per la lettura delle informazioni dei
Come riportato in \tabref{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 che contiene anche le informazioni relative ai permessi).
+\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 file,
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.
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
- \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
-struct utimbuf {
- time_t actime; /* access time */
- time_t modtime; /* modification time */
-};
- \end{lstlisting}
+ \includestruct{listati/utimbuf.h}
\end{minipage}
\normalsize
\caption{La struttura \structd{utimbuf}, usata da \func{utime} per modificare
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 (che ovviamente deve essere
eseguibile\footnote{per motivi di sicurezza il kernel ignora i bit \acr{suid}
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
Vedremo in \secref{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}).
\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 \funcd{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 \secref{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
+\secref{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 \figref{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)}
delle poche funzioni che non restituisce codici di errore.}
\end{prototype}
-Questa maschera è una caratteristica di ogni processo\footnote{è infatti
- contenuta nel campo \param{umask} di \struct{fs\_struct}, vedi
- \figref{fig:proc_task_struct}.} e viene utilizzata per impedire che alcuni
-permessi possano essere assegnati ai nuovi file in sede di creazione. I bit
-indicati nella maschera vengono infatti esclusi quando un nuovo file viene
-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}}
In \tabref{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{stiky} con la notazione
+specificati i bit di \acr{suid}, \acr{sgid} e \acr{sticky} con la notazione
compatta illustrata in \figref{fig:file_perm_bit}.
\begin{table}[!htb]
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 \struct{fs\_struct}, vedi
- \figref{fig:proc_task_struct}.} che è la directory che per il processo
-costituisce la radice dell'albero dei file e rispetto alla quale vengono
-risolti i pathname assoluti (si ricordi quanto detto in
-\secref{sec:file_organization}). La radice viene ereditata 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 \funcd{chroot}, il cui prototipo è:
+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 \figref{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 \secref{sec:file_organization}), ha per il
+processo il significato specifico di directory rispetto alla quale vengono
+risolti i pathname assoluti.\footnote{cioè quando un processo chiede la
+ risoluzione di un 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
+pathname assoluti da parte di un processo cambiando questa directory, così
+come si fa coi 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 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}.
\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 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 \secref{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
-sotto-directory 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.
+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 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