X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=blobdiff_plain;f=files.tex;h=a9f253b42f83c52eb13068c24339401fcfa4cf13;hb=60ea832813214f6bc4a9761a85d9d2b2038991aa;hp=b7ad2fd1c208f11fb3955eefe4949a84b68911af;hpb=dae47fe5a867149bb13d3b69126d92b8498b607b;p=gapil.git diff --git a/files.tex b/files.tex index b7ad2fd..a9f253b 100644 --- a/files.tex +++ b/files.tex @@ -327,8 +327,7 @@ sistemi POSIX uno degli attributi di un file aperto 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. - +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à @@ -382,14 +381,13 @@ precedente: ovviamente perch 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) è -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 di lavoro -corrente (\textit{current working directory}, su cui pure torneremo più avanti) -ed il pathname è detto \textsl{relativo}. +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 @@ -404,6 +402,236 @@ C normalmente si mette in file con l'estensione .c, ma questa 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 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{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 . + \item \texttt{EROFS} La directory su cui si vuole inserire il nuovo link è + su un filesystem montato readonly. + \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} @@ -413,12 +641,35 @@ operazioni connesse all'uso dei file. L'interfaccia l'header file \texttt{stdio.h}. Per ragioni storiche la struttura di dati che rappresenta un stream è stata -chiamata \texttt{FILE}, dato che le funzioni di libreria usano sempre come -parametri oggetti di tipo \texttt{FILE *} alle volte si usa il termine -puntatore a file come sinonimo di stream. - - - +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