\chapter{Files e directories}
\label{cha:files_and_dirs}

In questo capitolo tratteremo in dettaglio le modalità con cui si gestiscono
files e directories, ed in particolare esamineremo come è strutturato il
sistema base di protezioni e controllo di accesso ai files, e tutta
l'interfaccia che permette la manipolazione dei vari attributi di files e
directories. Tutto quello che riguarda invece la manipolazione dei contenuti è
lasciato ai capitoli successivi.


\section{La manipolazione delle caratteristiche dei files}
\label{sec:filedir_infos}

Come spiegato in \secref{sec:filedir_file_handling} tutte le informazioni
generali relative alle caratteristiche di ciascun file sono mantenute
nell'inode. Vedremo in questa sezione come sia possibile accedervi usando la
funzione \texttt{stat} ed esamineremo alcune funzioni utilizzabili per
manipolare una parte di questa informazione. Tutto quello che invece riguarda
il meccanismo di controllo di accesso ad i file e le relative funzioni di
manipolazione sarà invece esaminanto in \secref{sec:filedir_access_control}.


\subsection{Le funzioni \texttt{stat}, \texttt{fstat} e \texttt{lstat}}
\label{sec:filedir_stat}

La lettura delle informazioni relative ai file è fatta attraverso la famiglia
delle funzioni \texttt{stat}, questa è la funzione che il comando \texttt{ls}
usa per poter stampare tutti i dati dei files; il prototipo della funzione è
il seguente;
\begin{prototype}{unistd.h}
{int stat(const char *file\_name, struct stat *buf)}
  
  La funzione restituisce zero in caso di successo e -1 per un errore, in caso
  di errore \texttt{errno} viene settato ai valori:
  \begin{errlist}
  \item \texttt{EACCESS} Non c'è il permesso di accedere al file.
  \item \texttt{ENOTDIR} Una componente del pathname non è una directory.
  \item \texttt{EMLOOP} Ci sono troppi link simbolici nel pathname.
  \item \texttt{EFAULT} I puntatori usati sono fuori dallo spazio di indirizzi
    del processo.
  \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a
    completare l'operazione. 
  \item \texttt{ENAMETOOLONG} Il filename è troppo lungo.
  \end{errlist}
\end{prototype}

La struttura \texttt{stat} è definita nell'header \texttt{sys/stat.h} e in
generale dipende dall'implementazione, la versione usata da Linux è mostrata
in \nfig, così come riportata dalla man page (in realtà la definizione
effettivamente usata nel kernel dipende dall'archietettura e ha altri campi
riservati per estensioni come tempo più precisi, o per il padding dei campi).

\begin{figure}[!htb]
  \footnotesize
  \centering
  \begin{minipage}[c]{15cm}
    \begin{lstlisting}[]{}
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}
  \end{minipage} 
  \normalsize 
  \caption{La struttura \texttt{stat} per la lettura delle informazioni dei 
    file}
  \label{fig:sock_sa_gen_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
\texttt{sys/types.h}) 




\subsection{I tipi di file}
\label{sec:filedir_file_types}

Come riportato in \tabref{tab:fileintr_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 \texttt{stat} nel campo \texttt{st\_mode},
dato che il valore numerico può variare a seconda delle implementazioni


\subsection{La dimensione dei file}
\label{sec:filedir_file_size}

\subsection{I tempi dei file}
\label{sec:filedir_file_times}

\subsection{La funzione \texttt{utime}}
\label{sec:filedir_utime}




\section{Il controllo di accesso ai file}
\label{sec:filedir_access_control}


In unix è implementata da qualunque filesystem standard una forma elementare
(ma adatta alla maggior parte delle esigenze) di controllo di accesso ai
files. Torneremo sull'argomento in dettaglio più avanti (vedi
\secref{sec:filedir_access_control}), qui ci limitiamo ad una introduzione dei
concetti essenziali.

Si tenga conto poi che quanto diremo è vero solo per filesystem di tipo Unix,
e non è detto che sia applicabile (ed infatti non è vero per il filesystem di
Windows) a un filesystem qualunque. Esistono inoltre estensioni che permettono
di implementare le ACL (\textit{Access Control List}) che sono un meccanismo
di controllo di accesso molto più sofisticato.

Ad ogni file Unix associa sempre l'utente che ne è proprietario (il cosiddetto
\textit{owner}) e il gruppo di appartenenza, secondo il meccanismo degli uid e
gid accennato in \secref{sec:intro_multiuser}, e un insieme di permessi che
sono divisi in tre classi, e cioè attribuiti rispettivamente al proprietario,
a qualunque utente faccia parte del gruppo cui appartiene il file, e a tutti
gli altri utenti.

I permessi sono espressi da un insieme di 12 bit: di questi i nove meno
significativi sono usati a gruppi di tre per indicare i permessi base di
lettura, scrittura ed esecuzione (indicati rispettivamente con le lettere
\textit{w}, \textit{r} \textit{x}) applicabili rispettivamente al
proprietario, al gruppo, a tutti (una descrizione più dettagliata dei vari
permessi associati ai file è riportata in \secref{sec:filedir_suid_sgid}).  I
restanti tre bit sono usati per indicare alcune caratteristiche più complesse
(\textit{suid}, \textit{sgid}, e \textit{sticky}) su cui pure torneremo in
seguito (vedi \secref{sec:filedir_suid_sgid} e \secref{sec:filedir_sticky}).

Tutte queste informazioni sono tenute per ciascun file nell'inode. Quando un
processo cerca l'accesso al file esso controlla i propri uid e gid
confrontandoli con quelli del file e se l'operazione richiesta è compatibile
con i permessi associati al file essa viene eseguita, altrimenti viene
bloccata ed è restituito un errore di \texttt{EPERM}. Questo procedimento non
viene eseguito per l'amministratore di sistema (il cui uid è zero) il quale ha
pertanto accesso senza restrizione a qualunque file del sistema.

% In realtà il procedimento è più complesso di quanto descritto in maniera
% elementare qui; inoltre ad un processo sono associati diversi identificatori,
% torneremo su questo in maggiori dettagli in seguito in \secref{sec:proc_perms}.



\subsection{I flag \texttt{suid} e \texttt{sgid}}
\label{sec:filedir_suid_sgid}

\subsection{La titolarità di nuovi files e directory}
\label{sec:filedir_ownership}

\subsection{La funzione \texttt{access}}
\label{sec:filedir_access}

\subsection{La funzione \texttt{umask}}
\label{sec:filedir_umask}

\subsection{Le funzioni \texttt{chmod} e \texttt{fchmod}}
\label{sec:filedir_chmod}

\subsection{Il flag \texttt{sticky}}
\label{sec:filedir_sticky}

\subsection{Le funzioni \texttt{chown}, \texttt{fchown} e \texttt{lchown}}
\label{sec:filedir_chown}


\section{La manipolazione delle directories}
\label{sec:filedir_dir_handling}

\subsection{Le funzioni \texttt{mkdir} e \texttt{rmdir}} 
\label{sec:filedir_dir_creat_rem}

Per creare una nuova directory si può usare la seguente funzione, omonima
dell'analogo comando di shell \texttt{mkdir}; per accedere ai tipi usati
programma deve includere il file \texttt{sys/types.h}.

\begin{prototype}{sys/stat.h}
{int mkdir (const char * dirname, mode\_t mode)}
  Questa funzione crea una nuova directory vuota con il nome indicato da
  \texttt{dirname}, assegnandole i permessi indicati da \texttt{mode}. Il nome
  può essere indicato con il pathname assoluto o relativo.
  
  La funzione restituisce zero in caso di successo e -1 per un errore, in caso
  di errore \texttt{errno} viene settata secondo i codici di errore standard
  di accesso ai files (trattati in dettaglio in
  \secref{sec:filedir_access_control}) ai quali si aggiungono i seguenti:
  \begin{errlist}
  \item \texttt{EACCESS} 
    Non c'è il permesso di scrittura per la directory in cui si vuole inserire
    la nuova directory.
  \item \texttt{EEXIST} Un file (o una directory) con quel nome esiste di già. 
  \item \texttt{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 nell'hard-disk, ma potendo avere a che
    fare anche con filesystem di altri sistemi questo errore può presentarsi.
  \item \texttt{ENOSPC} Non c'è abbastanza spazio sul file system per creare
    la nuova directory.
  \item \texttt{EROFS} La directory su cui si vuole inserire la nuova
    directory è su un filesystem montato readonly.
  \end{errlist}
\end{prototype}
 

\subsection{Accesso alle directory}
\label{sec:filedir_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.

Per accedere al contenuto delle directory si usano i cosiddetti
\textit{directory streams} (chiamati così per l'analogia con i file stream);
la funzione \texttt{opendir} apre uno di questi stream e la funzione
\texttt{readdir} legge il contenuto della directory, i cui elementi sono le
\textit{directory entries} (da distinguersi da quelle della cache di cui
parlavamo in \secref{sec:fileintr_vfs}) in una opportuna struttura
\texttt{struct dirent}.


\subsection{La directory di lavoro}
\label{sec:filedir_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 (relativa appunto a questa directory).

Quando un utente effettua il login questa directory viene settata alla
cosiddetta \textit{home directory} del suo account, il comando \texttt{cd}
della shell consente di cambiarla a piacere, spostandosi da una directory ad
un'altra.  Siccome la directory corrente resta la stessa quando viene creato
un processo figlio, la directory corrente della shell diventa anche la
directory corrente di qualunque comando da essa lanciato.

Le funzioni qui descritte servono esaminare e cambiare la directory di lavoro
corrente. 

\begin{prototype}{unistd.h}{char * getcwd (char * buffer, size\_t size)}
  Restituisce il filename completo della directory di lavoro corrente nella
  stringa puntata da \texttt{buffer}, che deve essere precedentemente
  allocata, per una dimensione massima di \texttt{size}. Si può anche
  specificare un puntatore nullo come \textit{buffer}, nel qual caso la
  stringa sarà allocata automaticamente per una dimensione pari a
  \texttt{size} qualora questa sia diversa da zero, o della lunghezza esatta
  del pathname altrimenti. In questo caso si deve ricordare di disallocare la
  stringa una volta cessato il suo utilizzo.
  
  La funzione restituisce il puntatore \texttt{buffer} se riesce,
  \texttt{NULL} se fallisce, in quest'ultimo caso la variabile
  \texttt{errno} è settata con i seguenti codici di errore:
  \begin{errlist}
  \item \texttt{EINVAL} L'argomento \texttt{size} è zero e \texttt{buffer} non
    è nullo.
  \item \texttt{ERANGE} L'argomento \texttt{size} è più piccolo della
    lunghezza del pathname. 
  \item \texttt{EACCESS} Manca il permesso di lettura o di ricerca su uno dei
    componenti del pathname (cioè su una delle directory superiori alla
    corrente).
  \end{errlist}
\end{prototype}

Di questa funzione esiste una versione \texttt{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 \texttt{PATH\_MAX} (di solito 256 bytes, vedi
\secref{sec:xxx_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.

Una seconda funzione simile è \texttt{char * get\_current\_dir\_name(void)}
che è sostanzialmente equivalente ad una \texttt{getcwd(NULL, 0)}, con la sola
differenza che essa ritorna il valore della variabile di ambiente
\texttt{PWD}, che essendo costruita dalla shell può contenere anche dei
riferimenti simbolici.

Come già detto in unix anche le directory sono file, è possibile pertanto
riferirsi ad esse tramite il file descriptor dell'interfaccia a basso livello,
e non solo tramite il filename; per questo motivo ci sono due diverse funzioni
per cambiare directory di lavoro.

\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}.
\end{prototype}
  
\begin{prototype}{unistd.h}{int fchdir (int filedes)} 
  Analoga alla precedente, ma usa un file descriptor invece del pathname.
  
  Entrambe le funzioni restituiscono zero in caso di successo e -1 per un
  errore, in caso di errore \texttt{errno} viene settata secondo i codici di
  errore standard di accesso ai files (trattati in dettaglio in
  \secref{sec:filedir_access_control}) ai quali si aggiunge il codice
  \texttt{ENOTDIR} nel caso il \texttt{filename} indichi un file che non sia
  una directory.
\end{prototype}




%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}).

