\chapter{I files}
\label{cha:files}

Uno dei concetti fondamentali del design di unix è il cosiddetto
\textit{everything is a file}, cioè il fatto che l'accesso alle periferiche
viene gestito attraverso un'interfaccia astratta che tratta nello stesso modo
sia i normali file di dati che le periferiche. Si può accedere cioè a queste
ultime (con l'eccezione delle interfacce di rete) attraverso i cosiddetti file
di dispositivo (i \textit{device files}) che permettono ai programmi di
interfacciarsi alle varie periferiche come la seriale, la parallela, la
console, e gli stessi dischi.

\section{Concetti generali sui files}
\label{sec:file_gen}

Per poter accedere ai singoli file su disco è necessario l'uso di un
\textit{filesystem}, cioè di un'interfaccia del kernel che permetta di
strutturare l'informazione tenuta sullo spazio grezzo disponibile sui dischi
in files e directory. Sarà quest'ultimo a gestire l'accesso ai dati
memorizzati all'interno del disco stesso, e l'uso delle normali directory e
files.

%In generale un filesystem piazzerà opportunamente sul disco dei blocchi di
%informazioni riservate che tengono conto degli inodes allocati, di quelli
%liberi, e delle posizioni fisiche su disco dei dati contenuti nei files, per

Per poter accedere ai file contenuti in un disco occorrerà poi attivare il
filesystem \textit{montando} il disco (o la partizione del disco). 

In unix, a differenza di quanto avviene in altri sistemi operativi, tutti i
file vengono tenuti all'interno di un unico albero la cui radice (la directory
di \textit{root}) viene montata all'avvio. Pertanto un file viene identificato
dall'utente usando il suo \textit{pathname}, cioè il percorso completo che si
deve fare a partire dalla radice, per accedere al file.

Dopo la fase di inizializzazione il kernel riceve dal boot loader
l'indicazione di quale dispositivo contiene il filesystem da usare come punto
di partenza e questo viene montato come radice dell'albero (cioè nella
directory \texttt{/}); tutti gli ulteriori dischi devono poi essere inseriti
nell'albero utilizzando opportune subdirectory (in genere sotto
\texttt{/mnt}) .

Alcuni filesystem speciali (come \texttt{/proc} che contiene un'interfaccia ad
alcune strutture interne del kernel) sono generati automaticamente dal kernel
stesso, ma anche essi devono essere montati all'interno dell'albero.

All'interno dello stesso albero si potranno poi inserire anche gli altri
oggetti visti attraverso l'interfaccia che manipola i files come le FIFO, i
link, i socket e gli stessi i file di dispositivo (questi ultimi, per
convenzione, sono inseriti nella directory \texttt{/dev}).

\subsection{Il \textit{virtual filesystem} di linux}
\label{sec:file_vfs}

Esamineremo adesso come viene implementato l'accesso ai files in linux. Questa
sezione riporta informazioni sui dettagli di come il kernel gestisce i files,
ed è basata sul documento di Richard Goochs distribuito coi sorgenti del
kernel (\texttt{linux/Documentation/vfs.txt}).

L'argomento è abbastanza ``esoterico'' e questa sezione può essere saltata ad
una prima lettura; è bene però tenere presente che vengono introdotti qui
alcuni termini che potranno comparire in seguito, come \textit{inode},
\textit{dentry}, \textit{dcache}.

In linux il concetto di \textit{everything is a file} è stato implementato
attraverso il \textit{virtual filesystem} (da qui in avanti VFS) che è
l'interfaccia astratta che il kernel rende disponibile ai programmi in user
space attraverso la quale vengono manipolati i files, esso provvede anche
un'astrazione delle operazioni di manipolazione sui files che permette la
coesistenza di diversi filesystem all'interno dello stesso kernel.

La funzione più importante implementata dal VFS è la system call \texttt{open}
che permette di aprire un file. Dato un pathname viene eseguita una ricerca
dentro la \textit{directory entry cache} (la \textit{dcache}) una tabella di
hash che contiene tutte le \textit{directory entry} (in breve \textit{dentry})
che permette di associare in maniera rapida ed efficiente il pathname a una
specifica dentry.

Una singola dentry contiene in genere il puntatore ad un \textit{inode};
quest'ultimo è la struttura base che sta sul disco e che identifica un singolo
oggetto del VFS che può essere un file, una directory, una FIFO, un file di
dispositivo, o una qualsiasi altra cosa che possa essere rappresentata dal
VFS (sui tipi di files possibili torneremo in seguito).

Le dentries ``vivono'' in memoria e non vengono mai salvate su disco, vengono
usate per motivi di velocità, gli inodes invece vivono su disco e vengono
copiati in memoria quando serve, ed ogni cambiamento viene copiato
all'indietro sul disco, gli inodes che stanno in memoria sono inodes del VFS
ed è ad essi che puntano le singole dentry.

La dcache costituisce perciò una sorta di vista completa di tutto l'albero dei
files, ovviamente per non riempire tutta la memoria questa vista è parziale
(la dcache cioè contiene solo le dentry per i file per i quali è stato
richiesto l'accesso), quando si vuole risolvere un nuovo pathname il VFS deve
creare una nuova dentry e caricare l'inode corrispondente in memoria. 

Questo procedimento viene eseguito dalla metodo \texttt{lookup()} dell'inode
della directory che contiene il file; esso viene installato dallo specifico
filesystem su cui l'inode va a vivere.

Una volta che il VFS ha a disposizione la dentry (ed il relativo inode)
diventa possibile accedere a operazioni sul file come la \texttt{open} per
aprire il file o la \texttt{stat} per leggere i dati dell'inode e passarli in
user space.

L'apertura di un file richiede comunque un'altra operazione, l'allocazione di
una struttura di tipo \texttt{file} in cui viene inserito un puntatore alla
dentry e una struttura \verb|f_ops| che contiene i puntatori ai metodi che
implementano le operazioni disponibili sul file. In questo modo i processi in
user space possono accedere alle operazioni attraverso detti metodi, che
saranno diversi a seconda del tipo di file (o dispositivo) aperto. Un elenco
delle operazioni disponibili è riportato in \ntab.

% La struttura file viene poi inserita nella tavola dei file
% , non
% tutte le operazioni possibili sono definite per tutti i dispositivi; un elenco
% delle operazioni definite in linux è riportato in \ntab.

\begin{table}[htb]
  \centering
  \begin{tabular}[c]{c p{7cm}}
    \textbf{funzione} & \textbf{operazione} \\
    \hline
    \textit{open}    & apre il file \\
    \textit{read}    & legge dal file \\
    \textit{write}   & scrive sul file \\ 
    \textit{llseek}  & sposta la posizione corrente sul file \\
    \textit{ioctl}   & accede alle operazioni di controllo 
                       (tramite la \texttt{ioctl})\\
    \textit{readdir} & per leggere il contenuto di una directory \\
    \textit{poll}    & \\
    \textit{mmap}    & chiamata dalla system call \texttt{mmap}. 
                       mappa il file in memoria\\
    \textit{release} & chiamata quando l'ultima referenza a un file 
                       aperto è chiusa\\
    \textit{fsync}   & chiamata dalla system call \texttt{fsync} \\
    \textit{fasync}  & chiamate da \texttt{fcntl} quando è abilitato 
                       il modo asincrono per l'I/O su file. \\
    \hline
  \end{tabular}
  \caption{Operazioni sui file definite nel VFS.}
  \label{tab:file_operations}
\end{table}

In questo modo per ciascun file diventano utilizzabili una serie di operazioni
(non è dette che tutte siano disponibili), che costituiscono l'interfaccia
astratta del VFS, e qualora se ne voglia eseguire una il kernel andrà ad
utilizzare la opportuna routine dichiarata in \verb|f_ops| appropriata al tipo
di file in questione. 

Così sarà possibile scrivere sulla porta seriale come su un file di dati
normale; ovviamente certe operazioni (nel caso la \textit{seek}) non saranno
disponibili, però con questo sistema l'utilizzo di diversi filesystem è
immediato e (relativamente) trasparente per l'utente ed il programmatore.

\subsection{Proprietari e permessi}
\label{sec:file_perms}

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, 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 spiegato in \ref{sec:intro_usergroup}, 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. I restanti tre bit sono usati per indicare
alcune caratteristiche più complesse (\textit{suid}, \textit{sgid}, e
\textit{sticky}) su cui torneremo in seguito.

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, in quanto ad un processo sono associati diversi
identificatori, torneremo su questo in maggiori dettagli in seguito in
\ref{sec:proc_perms}.

\subsection{I tipi di files}
\label{sec:file_types}

Come detto in precedenza esistono vari tipi di oggetti implementati del VFS
per i quali è disponibile l'interfaccia astratta da esso provveduta. Un elenco
dei vari tipi di file è il seguente:
 
\begin{table}[htb]
  \begin{center}
    \begin{tabular}[c]{l l p{7cm}}
    \multicolumn{2}{c}{\textbf{Nome}} & \textbf{Descrizione} \\
    \hline
      \textit{regular file} & \textsl{file normale} &
      un file che contiene dei dati (l'accezione normale di file) \\
      \textit{directory} & \textsl{cartella o direttorio} &
      un file che contiene una lista di nomi associati a degli inodes \\
      \textit{symbolic link} & \textsl{collegamento simbolico} &
      un file che contiene un riferimento ad un altro file/directory \\
      \textit{char device} & \textsl{dispositivo a caratteri} &
      un file che identifica una periferica ad accesso sequenziale \\
      \textit{block device} & \textsl{dispositivo a blocchi} &
      un file che identifica una periferica ad accesso diretto \\
      \textit{fifo} & \textsl{tubo} &
      un file speciale che identifica una linea di comunicazione software
      (unidirezionale) \\
      \textit{socket} & \textsl{presa} &
      un file speciale che identifica una linea di comunicazione software
      (bidirezionale) \\
    \hline
    \end{tabular}
    \caption{Tipologia dei file definiti nel VFS}
    \label{tab:file_types}
  \end{center}
\end{table}

Tutto ciò non ha ovviamente nulla a che fare con la classificazione sui tipi
di file (in questo caso file di dati) in base al loro contenuto, o tipo di
accesso.  Una delle differenze principali con altri sistemi operativi (come il
VMS o windows) è che per unix tutti i file di dati sono identici e contengono
un flusso continuo di bytes; non esiste cioè differenza per come vengono visti
dal sistema file di diverso contenuto o formato (come nel caso di quella fra
file di testo e binari che c'è in windows) né c'è una strutturazione a record
per il cosiddetto ``accesso diretto'' come nel caso del VMS.

Una seconda differenza è nel formato dei file ascii; in unix la fine riga è
codificata in maniera diversa da windows o macintosh, in particolare il fine
riga è il carattere \texttt{LF} al posto del \texttt{CR} del mac e del
\texttt{CR LF} di windows. Questo può causare alcuni problemi qualora si
facciano assunzioni sul terminatore della riga.


\section{Una panoramica sull'I/O sui file}
\label{sec:file_io_base}

Per poter accedere al contenuto dei file occorre anzitutto aprirlo. Questo
crea un canale di comunicazione che permette di eseguire una serie di
operazioni. Una volta terminate le operazioni, il file dovrà essere chiuso, e
questo chiuderà il canale di comunicazione impedendo ogni ulteriore operazione.


\subsection{Le due interfacce ai file}
\label{sec:file_base_api}

In unix le modalità di accesso ai file e le relative interfacce di
programmazione sono due, basate su due diversi meccanismi di connessione. 

La prima è quella dei cosiddetti \textit{file descriptor} (descrittore di
file), che è specifica di unix e che provvede un accesso diretto a basso
livello non bufferizzato, con un'interfaccia primitiva ed essenziale; i file
descriptors sono rappresentati da numeri interi (cioè semplici variabili di
tipo \texttt{int}). L'interfaccia è definita nell'header \texttt{unistd.h}.

La seconda è quella degli \textit{stream}, che provvede un'interfaccia più
evoluta e un accesso bufferizzato. Questa è anche l'interfaccia standard usata
dal linguaggio C e perciò si trova anche su tutti i sistemi non unix. Gli
stream sono oggetti complessi e sono rappresentati da puntatori ad un
opportuna struttura definita dalle librerie del C, si accede ad essi sempre in
maniera indiretta utilizzando il tipo \texttt{FILE *}. L'interfaccia è
definita nell'header \texttt{stdio.h}.

Entrambe le interfacce possono essere usate per l'accesso ai file come agli
altri oggetti del VFS (pipes, socket, device), ma per poter accedere alle
operazioni di controllo sul particolare tipo di oggetto del VFS scelto occorre
usare l'interfaccia a basso livello dei file descriptor. Allo stesso modo
devono essere usati i file descriptor se si vuole ricorrere a modalità
speciali di I/O come il polling o il non-bloccante (vedi
\ref{sec:file_bohhhhh}).

Gli stream forniscono un'interfaccia di alto livello costruita sopra quella
dei file descriptor, che tratta tutti i file nello stesso modo, con
l'eccezione di poter scegliere tre diversi stili di bufferizzazione.  Il
maggior vantaggio degli stream è che l'interfaccia per le operazioni di
input/output è enormemente più ricca di quella dei file descriptor, che
provvedono solo funzioni elementari per la lettura/scrittura diretta di
blocchi di bytes.  In particolare dispongono di tutte le funzioni di
formattazione per l'input e l'output adatte per manipolare anche i dati in
forma di linee o singoli caratteri.

In ogni caso, dato che gli stream sono implementati sopra l'interfaccia a
basso livello dei file descriptor, è sempre possibile estrarre il file
descriptor da uno stream ed eseguirvi operazioni di basso livello, o associare
in un secondo tempo uno stream ad un file descriptor.

In generale, se non necessitano specificatamente le funzionalità di basso
livello, è opportuno usare sempre gli stream per la loro maggiore portabilità
essendo questi ultimi definito nello standard ISO C; l'interfaccia con i file
descriptor invece segue solo lo standard POSIX.1 dei sistemi unix ed è
pertanto di portabilità più limitata.

\subsection{Caratteristiche specifiche dei file in unix}
\label{sec:files_spec_unix}

Essendo un sistema multitasking e multiutente esistono alcune caratteristiche
specifiche di unix che devono essere tenute in conto nell'accesso ai file. È
infatti normale che più processi o programmi possano accedere
contemporaneamente allo stesso file e devono poter eseguire le loro operazioni
indipendentemente da quello che fanno gli altri processi.

Per questo motivo le strutture usate per all'accesso ai file sono relative al
processo che effettua l'accesso.  All'apertura di ogni file infatti viene
creata all'interno del processo una apposita struttura in cui sono memorizzati
tutti gli attributi del medesimo, che viene utilizzata per tutte le
operazioni. Questa è una struttura che resta locale al processo stesso; in
questo modo processi diversi possono usare le proprie strutture locali per
accedere ai file (che può essere sempre lo stesso) in maniera assolutamente
indipendente.

Questo ha delle conseguenze di cui è bene tenere conto; ad esempio in tutti i
sistemi POSIX uno degli attributi di un file aperto è la posizione corrente nel
file, cioè il punto nel file in cui verrebbe letto o scritto alla operazione
successiva. Essa è rappresentata da un numero intero che indica il numero di
bytes dall'inizio del file, che viene (a meno che non si apra il file in
append) inizializzato a zero all'apertura del medesimo.

Questo è uno dei dati che viene mantenuto nella suddetta struttura, per cui
ogni processo avrà la sua posizione corrente nel file, che non sarà
influenzata da quello che altri processi possono fare. Anzi, aprire un file
significa appunto creare ed inizializzare una tale struttura, per cui se si
apre due volte lo stesso file all'interno dello stesso processo, si otterrano
due file descriptor o due stream che avranno ancora un posizione corrente nel
file assolutamente indipendente.

Si tenga conto inoltre che un'altro dei dati contenuti nella struttura di
accesso è un riferimento all'inode del file, pertanto anche se il file viene
cancellato da un altro processo, sarà sempre possibile mantenere l'accesso,
e lo spazio su disco non verrà rilasciato fintanto che il file non sarà chiuso
e l'ultimo riferimento cancellato. È pertanto possibile (e pratica comune)
aprire un file provvisorio per cancellarlo immediatamente dopo; in questo modo
all'uscita del programma il file scomparirà definitivamente dal disco, ma il
file ed il suo contenuto saranno disponibili per tutto il tempo in cui il
processo è attivo.


\subsection{L'accesso ai files: nomi e directory}
\label{sec:file_names}

L'organizzazione dei nomi dei file deriva direttamente dall'organizzazione dei
medesimi nella gerarchia di directory descritta in \ref{sec:file_base}; una
directory comunque, come già specificato in \ref{sec:file_vfs}, è solo un
particolare tipo di file che il sistema riconosce come tale, che contiene le
informazioni che associano un inode ad un nome. Per questo, anche se è usuale
parlare di ``file in una directory'' in realtà una directory contiene solo dei
riferimenti ai file, non i file stessi.

I nomi contenuti nelle directory sono chiamati componenti (\textit{file name
  components}), un file può essere indicato rispetto alla directory corrente
semplicemente specificando il nome da essa contenuto. Una directory contiene
semplicemente un elenco di questi componenti, che possono corrispondere a un
qualunque oggetto del filesystem, compresa un'altra directory.

Un nome di file è composto da una serie di componenti separati da una
\texttt{/} (in linux più \texttt{/} consecutive sono considerate equivalenti
ad una sola). Il nome completo di un file viene usualmente chiamato
\textit{pathname}, anche se questo può generare confusione, dato che con
\textit{path} si indica anche un insieme di directory su cui effettuare una
ricerca (ad esempio quello in cui si cercano i comandi).

Il processo con cui si associa ad un pathname uno specifico file (cioè si
identifica l'inode a cui fare riferimento) è chiamato risoluzione del nome
(\textit{file name resolution} o \textit{pathname resolution}).
La risoluzione viene fatta esaminando il pathname da destra a sinistra e
localizzando ogni componente nella directory indicata dal componente
precedente: ovviamente perché il procedimento funzioni occorre che i
componenti indicati come directory esistano e siano effettivamente directory,
inoltre i permessi devono consentire l'accesso.

Se il pathname comincia per \texttt{/} la ricerca parte dalla directory radice
del processo che (a meno di un \textit{chroot} su cui torneremo in seguito,
vedi \ref{sec:file_chroot}) è la stessa per tutti i processi ed equivale alla
radice dell'albero (\ref{sec:file_gen}): in questo caso si parla di un
pathname \textsl{assoluto}. Altrimenti la ricerca parte dalla directory
corrente (su cui pure torneremo più avanti in \ref{sec:file_dir_working}) ed
il pathname è detto \textsl{relativo}.

I componenti \texttt{.} e \texttt{..} hanno un significato speciale e vengono
inseriti in ogni directory, il primo fa riferimento alla directory corrente e
il secondo alla directory \textsl{genitore} (\textit{parent directory}) cioè
la directory che contiene il riferimento alla directory corrente; nel caso
questa sia la directory radice allora il riferimento è a se stessa.

Infine si ricordi che in unix non esistono i tipi di file e che non c'è nessun
supporto per le estensioni come parte del filesystem. Ciò non ostante molti
programmi adottano delle convenzioni per i nomi dei file, ad esempio il codice
C normalmente si mette in file con l'estensione .c, ma questa è solo una
convenzione.


\section{L'interfaccia al filesystem}
\label{sec:file_filesys_interf}

Prima di entrare nei dettagli della manipolazione del contenuto dei file
esamineremo le funzioni utilizzate per operare sui file piuttosto che sul loro
contenuto. Le funzioni che esamineremo in questa sezione pertanto sono quelle
che permettono di esaminare e modificare le directory, rinominare o cancellare
i file, esaminare o settare i loro attributi.

\subsection{La directory di lavoro}
\label{sec:file_dir_working}

Come accennato 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. I prototipi di queste funzioni sono dichiarati in \texttt{unistd.h}. 

\begin{itemize}
\item \texttt{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 disallocara 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 sono ritornate le seguenti
  condizioni di errore:

  \begin{itemize}
  \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{EACCES} Manca il permesso di lettura o di ricerca su uno dei
    componenti del pathname (cioè su una delle directory superiori alla
    corrente).
  \end{itemize}
\end{itemize}

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 byters, vedi
\ref{sec:xxxx_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
(come vedremo in \ref{sec:file_dir_access}) 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{itemize}
\item \texttt{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 speficata dal pathname
  contenuto nella stringa \texttt{pathname}.
  
\item \texttt{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
  \ref{sec:file_err_acc}) ai quali si aggiunge il codice \texttt{ENOTDIR} nel
  caso il \texttt{filename} indichi un file che non sia una directory.
\end{itemize}

\subsection{Creazione di una directory} 
\label{sec:file_dir_creat}

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

\begin{itemize}
\item \texttt{char * 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 \ref{sec:file_err_acc}) ai
  quali si aggiungono i seguenti:
  \begin{itemize}
  \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 essite 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 monto readonly.
  \end{itemize}
\end{itemize}
 

\subsection{Accesso alle directory}
\label{sec:file_dir_access}

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 \ref{sec:file_vfs}) in una opportuna struttura \texttt{struct
dirent}.

\subsection{I link simbolici e i link diretti}
\label{sec:file_link}

Come si è già accennato nell'introduzione in un sistema unix quello che
caratterizza un file su disco è il suo \textit{inode}, è quindi 



\section{L'input/output di basso livello}
\label{sec:file_lowlev_io}
%
% Questa va per ultima. Va bene che e` la più usata, ma è basata sulle altre
%
\section{I file stream}
\label{sec:file_stream}

Esamineremo in questa sezione l'interfaccia per i file stream, le modalità per
crearli, e le funzioni disponibili per leggere, scrivere e compiere le varie
operazioni connesse all'uso dei file. L'interfaccia è accessibile includendo
l'header file \texttt{stdio.h}.

Per ragioni storiche la struttura di dati che rappresenta un stream è stata
chiamata \texttt{FILE}, questi oggetti sono creati dalle funzioni di libreria
e contengono tutte le informazioni necessarie a gestire le operazioni sugli
stream, come la posizione corrente, lo stato del buffer e degli indicatori di
stato e di fine del file. Per questo motivo gli utenti non devono mai
utilizzare direttamente o allocare queste strutture, ma usare sempre puntatori
del tipo \texttt{FILE *} (tanto che in certi caso il termine di puntatore a
file è diventato sinonimo di stream). 

\subsection{Gli stream standard}
\label{sec:file_stream_std}

Quando un programma viene lanciato il processo ha sempre tre stream
predefiniti aperti, che rappresentano i canali standard di input/output
prestabiliti per il processo; anche questi tre stream sono definiti
nell'header \texttt{stdio.h} e sono:

\begin{itemize}
\item \texttt{FILE * stdin} Lo \textit{standard input} cioè lo stream da cui
  il processo riceve ordinariamente i dati in ingresso. Normalmente è associato
  dalla shell all'input del terminale e prende i caratteri dalla tastiera.
\item \texttt{FILE * stdout} Lo \textit{standard input} cioè lo stream su cui
  il processo invia ordinariamente i dati in uscita. Normalmente è associato
  dalla shell all'output del terminale e scrive sullo schermo.
\item \texttt{FILE * stderr} Lo \textit{standard input} cioè lo stream su cui
  il processo è supposto inviare i messaaggi di errore. Normalmente anch'esso
  è associato dalla shell all'output del terminale e scrive sullo schermo.
\end{itemize}

In linux 


%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 \ref{sec:file_perms}), le date (vedi
%\ref{sec:file_times}).

