Grandi pulizie di primavera... dimmi te se uno deve sprecare le ferie cosi`
[gapil.git] / files.tex
diff --git a/files.tex b/files.tex
deleted file mode 100644 (file)
index e3c994d..0000000
--- a/files.tex
+++ /dev/null
@@ -1,718 +0,0 @@
-\chapter{I files: introduzione}
-\label{cha:files}
-Uno dei concetti fondamentali del design di unix è il cosiddetto
-\textit{everything is a file}, cioè il fatto che l'accesso ai vari dispositivi
-di I/O del computer viene effettuato attraverso un'interfaccia astratta che
-tratta le periferiche allo stesso modo degli usuali file di dati.
-
-Si può accedere cioè a qualunque periferica del computer, dalla seriale, alla
-parallela, alla console, e agli stessi dischi, (unica eccezione le interfacce
-di rete, che che non rientrano bene nell'astrazione) attraverso i cosiddetti
-file di dispositivo (i \textit{device files}). Questi sono dei file speciali
-agendo sui quali i programmi possono leggere, scrivere e compiere operazioni
-sulle perferiche, usando le stesse funzioni che si usano per i normali file di
-dati.
-
-\section{Concetti generali riguardanti i files}
-\label{sec:file_gen}
-
-Visto il ruolo fondamentale che i files vengono ad assumere in un sistema
-unix, è anzitutto opportuno fornire un'introduzione dettagliata su come essi
-vengono trattati dal sistema. In particolare occorre tenere presente dov'è che
-si situa il limite fondamentale fra kernel space e user space che tracciavamo
-al Cap.~\ref{cha:intro_unix}.
-
-Partiamo allora da come viene strutturata nel sistema la disposizione dei
-file: per potervi accedere il kernel usa una apposita interfaccia che permetta
-di strutturare l'informazione tenuta sullo spazio grezzo disponibile sui
-dischi, cioè quello che si chiama un \textit{filesystem}. 
-
-Sarà attraverso quest'ultimo che il kernel andrà a gestire l'accesso ai dati
-memorizzati all'interno del disco stesso, strutturando l'informazione in files
-e directory.  Per poter accedere ai file contenuti in un disco occorrerà
-perciò attivare il filesystem, questo viene fatto \textsl{montando} il disco
-(o la partizione del disco).
-
-%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
-
-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 quello che viene chiamato \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.
-
-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} (in breve \textit{dcache}) che è
-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 sia esso un file ordinario, 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 stanno 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.
-
-\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 della seriale ad esempio la
-\textit{seek}) non saranno disponibili, però con questo sistema l'utilizzo di
-diversi filesystem (come quelli usati da Windows o MacOs) è 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{manicotto} &
-      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} (o \verb|\n|) al posto del \texttt{CR}
-(\verb|\r|) 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'uso dei 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 gli stream 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 una 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 ai
-dati, 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 \textsl{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{filename} o \textit{pathname}, anche se quest'ultimo 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 è, appunto, 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 la variabile
-  \texttt{errno} è settata con i seguenti codici 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 montato 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}
-
-Una delle caratteristiche più usate quando si opera con i file è quella di
-poter creare dei nomi fittizi (alias o collegamenti) per potersi riferire allo
-stesso file accedendovi da directory diverse. Questo è possibile anche in
-ambiente unix, dove tali collegamenti sono usualmente chiamati \textit{link},
-ma data la struttura del sistema ci sono due metodi sostanzialmente diversi
-per fare questa operazione.
-
-Come si è già accennato nell'introduzione in un sistema unix l'accesso al
-contenuto di un file su disco avviene attraverso il suo \textit{inode}, e il
-nome che si trova in una directory è solo una etichetta associata ad un
-puntatore a detto inode.  Questo significa che la realizzazione di un links è
-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
-rispetto agli altri.
-
-Per aggiungere un nome ad un inode si utilizza la funzione \texttt{link}, e si
-suole chiamare questa associazione un collegamento diretto (o \textit{hard
-  link}).  La creazione di un nuovo link diretto non copia il contenuto del
-file, ma si limita ad aumentare di uno il numero di referenze al file (uno dei
-dati contenuti nell'inode) aggiungendo il nuovo nome ai precedenti. Si noti
-che uno stesso file può essere così richiamato in diverse directory.
-
-Siccome tutto ciò funziona facendo riferimento ad un inode, questa funzione
-può essere applicata soltanto per file che risiedono sullo stesso filesystem,
-(dato che solo in questo caso è garantita l'unicità dell'inode) e solo per
-filesystem di tipo unix. Inoltre in linux non è consentito eseguire un link
-diretto ad una directory.
-
-Per ovviare a queste limitazioni i sistemi unix supportano un'altra forma di
-link (i cosiddetti \textit{soft link} o \textit{symbolic link}), che sono,
-come avviene in altri sistemi operativi, dei file che contengono il
-semplicemente il riferimento ad un altro file (o directory). In questo modo è
-possibile effettuare link anche attraverso filesystem diversi e a directory, e
-pure 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 la chiamata
-ad una \texttt{open} o una \texttt{stat} su un link simbolico comporta la
-lettura del contenuto del medesimo e l'applicazione della funzione al file
-specificato da quest'ultimo. Invece altre funzioni come quelle per cancellare
-o rinominare i file operano direttamente sul link simbolico. Inoltre esistono
-funzioni apposite, come la \texttt{readlink} e la \texttt{lstat} per accedere
-alle informazioni del link invece che a quelle del file a cui esso fa
-riferimento.
-
-Le funzioni per operare sui link sono le seguenti, esse sono tutte dichiarate
-nell'header file \texttt{unistd.h}.
-
-\begin{itemize}
-\item \texttt{int link(const char * oldname, const char * newname)}
-  
-  Crea un nuovo link diretto al file indicato da \texttt{oldname} dandogli
-  nome \texttt{newname}.
-  
-  La funzione restituisce zero in caso di successo e -1 per un errore, in caso
-  di errore. La variabile \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{EXDEV} \texttt{oldname} e \texttt{newname} non sono sullo
-    stesso filesystem.
-  \item \texttt{EPERM} il filesystem che contiene \texttt{oldname} e
-    \texttt{newname} non supporta i link diretti.
-  \item \texttt{EACCESS} 
-    Non c'è il permesso di scrittura per la directory in cui si vuole creare
-    il nuovo link.
-  \item \texttt{EEXIST} Un file (o una directory) con quel nome esiste di
-    già.
-  \item \texttt{EMLINK} Ci sono troppi link al file \texttt{oldname} (il
-    numero massimo è specificato dalla variabile \texttt{LINK\_MAX}, vedi
-    \ref{sec:sys_limits}.
-  \item \texttt{ENOSPC} La directory in cui si vuole creare il link è piena e
-    non può essere ampliata.
-  \item \texttt{EROFS} La directory su cui si vuole inserire il nuovo link è
-    su un filesystem montato readonly.
-  \end{itemize}
-\end{itemize}
-
-
-\begin{itemize}
-\item \texttt{int symlink(const char * oldname, const char * newname)}
-  
-  Crea un nuovo link simbolico al file indicato da \texttt{oldname} dandogli
-  nome \texttt{newname}.
-  
-  La funzione restituisce zero in caso di successo e -1 per un errore, in caso
-  di errore. La variabile \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{EEXIST} Un file (o una directory) con quel nome esiste di
-    già.
-  \item \texttt{EROFS} La directory su cui si vuole inserire il nuovo link è
-    su un filesystem montato readonly.
-  \item \texttt{ENOSPC} La directory o il filesystem in cui si vuole creare il
-    link è piena e non c'è ulteriore spazio disponibile.
-  \item \texttt{ELOOP} Ci sono troppi link simbolici nella risoluzione di
-    \texttt{oldname} o di \texttt{newname}.
-  \end{itemize}
-\end{itemize}
-
-
-
-
-\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}).
-