X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=blobdiff_plain;f=filedir.tex;h=c5f46756d453a2f904c6ceff6389c33f7401d6b6;hb=f15d1cc1ff7e1b4d15d434144862a5505bd33f0a;hp=f68576f0cb859b5d5ea18e4c03aaffe3411b0e2c;hpb=09fff83335c84e1290f725341b0959344e5a7b03;p=gapil.git diff --git a/filedir.tex b/filedir.tex index f68576f..c5f4675 100644 --- a/filedir.tex +++ b/filedir.tex @@ -6,7 +6,7 @@ directories, ed in particolare approfondiremo i dettagli su come la struttura dei files in un sistema unix; esamineremo poi 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 e +directories. Tutto quello che riguarda invece la manipolazione dei contenuti è lasciato ai capitoli successivi. Le funzioni che esamineremo in questo capitolo pertanto sono quelle che @@ -18,68 +18,71 @@ cancellare i files ed esaminare o cambiare i loro attributi. \label{sec:filedir_org} L'organizzazione dei nomi dei file deriva direttamente dall'organizzazione dei -medesimi nell'albero descritto brevemente in \ref{sec:fileintr_overview}; una -directory comunque, come già specificato in \ref{sec:fileintr_vfs}, è solo un -particolare tipo di file che contiene le informazioni che associano un nome al -contenuto. 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; l'albero viene -appunto creato inserendo directory in altre directory. - -Il nome di file generico è 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{pathname}, e anche se il manuale della glibc -depreca questo nome (poichè genererebbe confusione, dato che con \textit{path} -si indica anche un insieme di directory su cui effettuare una ricerca, come -quello in cui si cercano i comandi) l'uso è ormai così comune che è senz'altro -più chiaro dell'alternativa proposta. - -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. +medesimi nell'albero descritto brevemente in \secref{sec:fileintr_overview}; +una directory comunque, come già specificato in \secref{sec:fileintr_vfs}, è +solo un particolare tipo di file che contiene le informazioni che associano un +nome al contenuto. Per questo, anche se è usuale parlare di ``file in una +directory'' in realtà una directory contiene solo delle etichette per fare +riferimento ai file stessi. + +I manuale delle librerie del C chiama i nomi contenuti nelle directory +\textsl{componenti} (in inglese \textit{file name components}), noi li +chiameremo più semplicemente nomi. Un file può essere indicato rispetto alla +directory corrente semplicemente specificando il nome da essa contenuto. Una +directory contiene semplicemente un elenco di questi nomi, che possono +corrispondere a un qualunque oggetto del filesystem, compresa un'altra +directory; l'albero viene appunto creato inserendo directory in altre +directory. + +Il nome completo di file generico è composto da una serie di questi +\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{pathname}, e anche se il manuale della +glibc depreca questo nome (poichè genererebbe confusione, dato che con +\textit{path} si indica anche un insieme di directory su cui effettuare una +ricerca, come quello in cui si cercano i comandi) l'uso è ormai così comune +che è senz'altro più chiaro dell'alternativa proposta. + +Il processo con cui si associa ad un pathname uno specifico file è 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 nome nella directory indicata dal nome +precedente: ovviamente perché il procedimento funzioni occorre che i nomi +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; questa, a meno di un \textit{chroot} (su cui torneremo in -seguito, vedi \ref{sec:proc_chroot}) è la stessa per tutti i processi ed +seguito, vedi \secref{sec:proc_chroot}) è la stessa per tutti i processi ed equivale alla directory radice dell'albero (come descritto in -\ref{sec:fileintr_overview}): in questo caso si parla di un pathname +\secref{sec:fileintr_overview}): in questo caso si parla di un pathname \textsl{assoluto}. Altrimenti la ricerca parte dalla directory corrente (su -cui torneremo più avanti in \ref{sec:filedir_work_dir}) ed il pathname è detto -\textsl{relativo}. +cui torneremo più avanti in \secref{sec:filedir_work_dir}) ed il pathname è +detto \textsl{relativo}. -I componenti \texttt{.} e \texttt{..} hanno un significato speciale e vengono +I nomi \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. -\section{La manipolazione di files e directories} -\label{sec:filedir_handling} +\section{L'architettura di gestione dei file} +\label{sec:filedir_file_handling} Per capire fino in fondo le proprietà di files e directories in un sistema unix ed il funzionamento delle relative funzioni di manipolazione occorre una -breve introduzione agli oggetti su cui è basato un filesystem unix; in -particolare si riprenderanno, approfondendoli, i concetti di \textit{inode} e -\textit{dentry} brevemente introdotti in \ref{sec:fileintr_vfs}. +breve introduzione sulla gestione dei medesimo e sugli oggetti su cui è basato +un filesystem unix; in particolare si riprenderà, approfondendolo sul piano +dell'uso nelle funzioni di libreria, il concetto di \textit{inode} di cui +abbiamo brevemente accennato le caratteristiche (dal lato dell'implementazione +nel kernel) in \secref{sec:fileintr_vfs}. -\subsection{Il funzionamento di un filesystem} +\subsection{Il funzionamento di un filesystem unix} \label{sec:filedir_filesystem} -Come già accennato in \ref{sec:fileintr_overview} linux (ed ogni unix in +Come già accennato in \secref{sec:fileintr_overview} linux (ed ogni unix in generale) organizza i dati che tiene su disco attraverso l'uso di un filesystem. Una delle caratteristiche di linux rispetto agli altri unix è quella di poter supportare grazie al VFS una enorme quantità di filesystem @@ -90,7 +93,7 @@ comuni di un qualunque filesystem standard unix. Dato un disco lo spazio fisico viene usualmente diviso in partizioni; ogni partizione può contenere un filesystem; quest'ultimo è in genere strutturato -secondo \nfig, con una lista di inodes all'inizio e il resto dello spazio aa +secondo \nfig, con una lista di inodes all'inizio e il resto dello spazio a disposizione per i dati e le directory. \begin{figure}[htb] @@ -100,67 +103,69 @@ disposizione per i dati e le directory. \label{fig:filedir_disk_filesys} \end{figure} -Se si va ad esaminare come è strutturata l'informazione all'interno del -filesystem (tralasciando le parti che non riguardano direttamente la gestione -di file e directory come il super-block) avremo una situazione del tipo di -quella esposta in \nfig. - +Se si va ad esaminare come è strutturata l'informazione all'interno di un +singolo filesystem (tralasciando le parti connesse alla strutturazione e al +funzionamento del filesystem stesso come il super-block) avremo una situazione +del tipo di quella esposta in \nfig. \begin{figure}[htb] \centering \caption{Organizzazione di un filesystem} \label{fig:filedir_filesys_detail} \end{figure} +da questa figura si evidenzano alcune caratteristiche su cui è bene porre +attenzione in quanto sono fondamentali per capire il funzionamento delle +funzioni che manipolano i file e le directory su cui torneremo fra poco; in +particolare è opportuno ricordare sempre che: - -Quanto mostrato in \curfig\ mette in evidenza alcune caratteristiche di un -filesystem unix su cui è bene porre attenzione in quanto sono fondamentali per -capire il funzionamento delle funzioni che manipolano i file e le directory su -cui torneremo fra poco; in particolare è opportuno ricordare sempre che: - -\begin{itemize} +\begin{enumerate} \item L'\textit{inode} contiene tutte le informazioni riguardanti il file: il tipo di file, i permessi di accesso, le dimensioni, i puntatori ai blocchi fisici che contengono i dati e così via; le informazioni che la funzione - \texttt{stat} fornisce provengono dall'inode; dentro una directory si - troverà solo il nome del file e il numero dell'inode ad esso associato, cioè - una \textit{dentry}. + \texttt{stat} fornisce provengono dall'\textit{inode}; dentro una directory + si troverà solo il nome del file e il numero dell'\textit{inode} ad esso + associato, cioè quella che da qui in poi chiameremo una \textsl{voce} + (traduzione approssimata dell'inglese \textit{directory entry}, che non + useremo anche per evitare confusione con le \textit{dentries} del kernel di + cui si parlava in \secref{sec:fileintr_vfs}). -\item Come mostrato in \curfig si possono avere più dentries che puntano allo - stesso inode. Ogni inode ha un contatore che contiene il numero di - riferimenti (\textit{link count}) che sono stati fatti ad esso, solo quando - questo contatore si annulla il file può essere cancellato. Per questo in - generale non esiste una funzione che cancelli un file, ma solo la funzione - \texttt{unlink} che si chiama così proprio perché che toglie un riferimento - da una directory (cancellando la dentry), il che non comporta - automaticamente pure la eliminazione dei blocchi sul disco. +\item Come mostrato in \curfig si possono avere più voci che puntano allo + stesso \textit{inode}. Ogni \textit{inode} ha un contatore che contiene il + numero di riferimenti (\textit{link count}) che sono stati fatti ad esso; + solo quando questo contatore si annulla i dati del file vengono + effettivamente rimossi dal disco. Per questo la funzione per cancellare un + file si chiama \texttt{unlink}, ed in realtà non cancella affatto i dati del + file, ma si limita a eliminare la relativa voce da una directory e + decrementare il numero di riferimenti nell'\textit{inode}. + +\item Il numero di \textit{inode} nella voce si riferisce ad un \textit{inode} + nello stesso filesystem e non ci può essere una directory che contiene + riferimenti ad \textit{inodes} relativi ad altri filesystem. Questo limita + l'uso del comando \texttt{ln} (che crea una nuova voce per un file + esistente, con la funzione \texttt{link}) al filesystem corrente. -\item Siccome il numero di inode nella dentry si riferisce ad un inode nello - stesso filesystem non ci può essere una directory che contiene riferimenti - ad inodes relativi ad altri filesystem, questo limita l'uso del comando - \texttt{ln} (che crea una nuova dentry per un file esistente, con la - funzione \texttt{link}) al filesystem corrente. - \item Quando si cambia nome ad un file senza cambiare filesystem il contenuto - del file non deve essere spostato, ma basta creare una nuova dentry per - l'inode in questione rimuovendo la vecchia (che è la modalità in cui opera - normalmente il comando \texttt{mv} attraveso la funzione \texttt{rename}). + del file non deve essere spostato, viene semplicemente creata una nuova voce + per l'\textit{inode} in questione e rimossa la vecchia (questa è la modalità + in cui opera normalmente il comando \texttt{mv} attraverso la funzione + \texttt{rename}). -\end{itemize} +\end{enumerate} -Infine è bene avere presente che esiste un numero di riferimenti anche per le -directories, se a partire dalla situazione mostrata in \curfig\ creiamo una -nuova directory \texttt{textdir} avremo una situazione come quella in \nfig, -dove per chiarezza abbiamo aggiunto dei numeri di inode. +Infine è bene avere presente che essendo file pure loro, esiste un numero di +riferimenti anche per le directories; per cui se ad esempio a partire dalla +situazione mostrata in \curfig\ creiamo una nuova directory \texttt{textdir} +nella directory corrente avremo una situazione come quella in \nfig, dove per +chiarezza abbiamo aggiunto dei numeri di inode. La nuova directory avrà allora un numero di riferimenti pari a due, in quanto è referenziata dalla directory da cui si era partiti (in cui è inserita la -nuova dentry che fa riferiemto a \texttt{textdir}) e dalla dentry \texttt{.} +nuova voce che fa riferimento a \texttt{textdir}) e dalla voce \texttt{.} che è sempre inserita in ogni directory; questo vale sempre per ogni directory che non contenga a sua volta altre directories. Al contempo la directory da cui si era partiti avrà un numero di riferiementi di almeno tre, in quanto -adesso sarà referenziata anche dalla dentry \texttt{..} di \texttt{textdir}. +adesso sarà referenziata anche dalla voce \texttt{..} di \texttt{textdir}. \subsection{Le funzioni \texttt{link} e \texttt{unlink}} @@ -173,66 +178,206 @@ 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 è appena visto 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 link è 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. +Come si è appena detto l'accesso al contenuto di un file su disco avviene +attraverso il suo 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 link è 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}; si suole chiamare questo tipo di 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 aggiungendo il nuovo nome ai precedenti. Si noti che uno stesso file può -essere così richiamato in diverse directory. - -\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}. +\textit{hard link}). Il prototipo della funzione e le sue caratteritiche +principali, come risultano dalla man page, sono le seguenti: +\begin{prototype}{unistd.h} +{int link(const char * oldpath, const char * newpath)} + Crea un nuovo collegamento diretto al file indicato da \texttt{oldpath} + dandogli nome \texttt{newpath}. 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:filedir_access_control}) ai quali si aggiungono i seguenti: - - \begin{itemize} - \item \texttt{EXDEV} \texttt{oldname} e \texttt{newname} non sono sullo + di errore. La variabile \texttt{errno} viene settata secondo i seguenti + codici di errore: + \begin{errlist} + \item \texttt{EXDEV} \texttt{oldpath} e \texttt{newpath} 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 + \item \texttt{EPERM} il filesystem che contiene \texttt{oldpath} e + \texttt{newpath} non supporta i link diretti, oppure \texttt{oldpath} è + una directory. + \item \texttt{EFAULT} una delle stringhe passate come parametri è fuori + dello spazio di indirizzi del processo. + \item \texttt{EACCESS} errore di accesso (mancano i permessi per scrivere o + per attraversare le directories), vedi \secref{sec:filedir_access_control} + per i dettagli. + \item \texttt{ENAMETOOLONG} una dei due pathname è troppo lungo. + \item \texttt{ENOENT} un componente di \texttt{oldpath} o \texttt{newpath} + non esiste o è un link simbolico spezzato. + \item \texttt{ENOTDIR} un componente di \texttt{oldpath} o \texttt{newpath} + non è una directory. + \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a + completare l'operazione. + \item \texttt{EROFS} la directory su cui si vuole inserire il nuovo link è + su un filesystem montato readonly. + \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 + \item \texttt{EMLINK} ci sono troppi link al file \texttt{oldpath} (il numero massimo è specificato dalla variabile \texttt{LINK\_MAX}, vedi - \ref{sec:xxx_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} - - + \secref{sec:xxx_limits}). + \item \texttt{ELOOP} si incontrati troppi link simbolici nella risoluzione + di \texttt{oldpath} o \texttt{newpath}. + \item \texttt{ENOSPC} la directory in cui si vuole creare il link non ha + spazio per ulteriori voci. + \item \texttt{EIO} c'è stato un errore di input/output. + \end{errlist} +\end{prototype} + +La creazione di un nuovo collegamento diretto non copia il contenuto del file, +ma si limita ad aumentare di uno il numero di referenze al file aggiungendo il +nuovo nome ai precedenti. Si noti che uno stesso file può essere così +richiamato in diverse directory. + +Per quanto dicevamo in \secref{sec:filedir_filesystem} la creazione del +collegamento diretto è possibile solo se entrambi i pathname sono nello stesso +filesytem; inoltre il filesystem deve supportare i collegamenti diretti (non è +il caso ad esempio del filesystem \texttt{vfat} di windows). + +La funzione opera sui file ordinari, come sugli altri oggetti del filesystem, +ma solo l'amministratore è in grado di creare un collegamento diretto ad +un'altra directory, questo lo si fa perché in questo caso è possibile creare +dei circoli nel filesystem (vedi \secref{sec:filedir_symlink}) che molti +programmi non sono in grado di gestire e la cui rimozione diventa estremamente +complicata (in genere occorre far girare il programma \texttt{fsck} per +riparare il filesystem); data la sua pericolosità in linux questa +caratteristica è stata disabilitata, e la funzione restituisce l'errore +\texttt{EPERM}. + +La rimozione di un file (o più precisamente della voce che lo referenzia) si +effettua con la funzione \texttt{unlink}; il suo prototipo è il seguente: + +\begin{prototype}{unistd.h}{int unlink(const char * pathname)} + Cancella il nome specificato dal pathname nella relativa directory e + decrementa il numero di riferimenti nel relativo inode. Nel caso di link + simbolico cancella il link simbolico; nel caso di socket, fifo o file di + dispositivo rimuove il nome, ma come per i file i processi che hanno aperto + uno di questi oggetti possono continuare ad utilizzarlo. + + La funzione restituisce zero in caso di successo e -1 per un errore, nel + qual caso il file non viene toccato. La variabile \texttt{errno} viene + settata secondo i seguenti codici di errore: + \begin{errlist} + \item \texttt{EACCESS} errore di accesso (mancano i permessi per scrivere o + per attraversare le directories), vedi \secref{sec:filedir_access_control} + per i dettagli. + \item \texttt{EPERM} il filesystem che contiene \texttt{pathname} non + consente l'operazione. + \item \texttt{EFAULT} la stringa passata come parametro è fuori dello spazio + di indirizzi del processo. + \item \texttt{ENAMETOOLONG} il pathname troppo lungo. + \item \texttt{ENOENT} uno dei componenti del pathname non esiste o è un link + simbolico spezzato. + \item \texttt{ENOTDIR} uno dei componenti del pathname non è una directory. + \item \texttt{EISDIR} \texttt{pathname} fa riferimento a una directory. + \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a + completare l'operazione. + \item \texttt{EROFS} \texttt{pathname} è su un filesystem montato in sola + lettura. + \item \texttt{ELOOP} ci sono troppi link simbolici nella risoluzione del + pathname. + \item \texttt{EIO} errore di input/output. + \end{errlist} +\end{prototype} + +Per cancellare una voce in una directory è necessario avere il permesso di +scrittura su di essa (dato che si va a rimuovere una voce dal suo contenuto) e +il diritto di esecuzione sulla directory che la contiene (torneremo in +dettaglio sui permessi e gli attributi fra poco), se inoltre lo +\textit{sticky} bit è settato occorrerà anche essere proprietari del file o +proprietari della directory (o root, per cui nessuna delle restrizioni è +applicata). + +Una delle caratteristiche di queste funzioni è che la creazione/rimozione +della nome dalla directory e l'incremento/decremento del numero di riferimenti +nell'inode deve essere una operazione atomica (cioè non interrompibile da +altri) processi, per questo entrambe queste funzioni sono realizzate tramite +una singola system call. + +Si ricordi infine che il file non viene eliminato dal disco fintanto che tutti +i riferimenti ad esso sono stati cancellati, solo quando il \textit{link + count} mantenuto nell'inode diventa zero lo spazio occupato viene rimosso. A +questo però si aggiunge una altra condizione, e cioè che non ci siano processi +che abbiano detto file aperto. Come accennato questa proprietà viene spesso +usata per essere sicuri di non lasciare file temporanei su disco in caso di +crash dei programmi; la tecnica è quella di aprire il file e chiamare +\texttt{unlink} subito dopo. \subsection{Le funzioni \texttt{remove} e \texttt{rename}} \label{sec:filedir_cre_canc} +Al contrario di quanto avviene con altri unix in linux non è possibile usare +\texttt{unlink} sulle directory, per cancellare una directory si può usare la +funzione \texttt{rmdir} (vedi \secref{sec:filedir_dir_creat_rem}), oppure la +funzione \texttt{remove}. Questa è la funzione prevista dallo standard ANSI C +per cancellare un file o una directory (e funziona anche per i sistemi che non +supportano i link diretti), che per i file è identica alla \texttt{unlink} e +per le directory è identica alla \texttt{rmdir}: + +\begin{prototype}{stdio.h}{int remove(const char *pathname)} + Cancella un nome dal filesystem. Usa \texttt{unlink} per i file e + \texttt{rmdir} per le directory. + + La funzione restituisce zero in caso di successo e -1 per un errore, nel + qual caso il file non viene toccato. Per i codici di errori vedi quanto + riportato nella descrizione di \texttt{unlink} e \texttt{rmdir}. +\end{prototype} + +Per cambiare nome ad un file si usa invece la funzione \texttt{rename}, il +vantaggio nell'uso di questa funzione al posto della chiamata successiva di +\texttt{unlink} e \texttt{link} è che l'operazione è eseguita atomicamente, in +questo modo non c'è la possibilità che un processo che cerchi di accedere al +nuovo nome dopo che il vecchio è stato cambiato lo trovi mancante. + +\begin{prototype}{stdio.h} +{int rename(const char *oldpath, const char *newpath)} + Rinomina un file, spostandolo fra directory diverse quando richiesto. + + La funzione restituisce zero in caso di successo e -1 per un errore, nel + qual caso il file non viene toccato. La variabile \texttt{errno} viene + settata secondo i seguenti codici di errore: + \begin{errlist} + \item \texttt{EFAULT} la stringa \texttt{filename} è fuori dello spazio di + indirizzi del processo. + \item \texttt{EACCESS} Non c'è il permesso di scrittura per la directory in + cui si vuole creare il nuovo link o una delle directory del pathname non + consente la ricerca (permesso di esecuzione). + \item \texttt{EPERM} il pathname indica una directory o il filesystem che + contiene \texttt{filename} non consente l'operazione. + \item \texttt{EROFS} I file sono su un filesystem montato in sola lettura. + \item \texttt{ENAMETOOLONG} il pathname è troppo lungo. + \item \texttt{ENOENT} Uno dei componenti del pathname non esiste o è un link + simbolico spezzato. + \item \texttt{ENOTDIR} Uno dei componenti del pathname non è una directory. + \item \texttt{ENOMEM} Memoria insufficiente nel kernel. + \item \texttt{ELOOP} Ci sono troppi link simbolici nella risoluzione del + pathname. + \item \texttt{EISDIR} + \item \texttt{EXDEV} + \item \texttt{ENOTEMPTY} + \item \texttt{EBUSY} + \item \texttt{EINVAL} + \item \texttt{EMLINK} + \item \texttt{ENOSPC} + + \end{errlist} +\end{prototype} \subsection{I link simbolici} \label{sec:filedir_sym_link} -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. +Siccome la funzione \texttt{link} crea riferimenti agli inodes, essa può +funzionare soltanto per file che risiedono sullo stesso filesystem, dato che +in questo caso è garantita l'unicità dell'inode, e solo per un 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, @@ -251,21 +396,46 @@ 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}. +Le funzioni per operare sui link simbolici sono le seguenti, esse sono tutte +dichiarate nell'header file \texttt{unistd.h}. -\begin{itemize} -\item \texttt{int symlink(const char * oldname, const char * newname)} - +\begin{prototype}{unistd.h} +{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:filedir_access_control}) ai quali si aggiungono i seguenti: + \secref{sec:filedir_access_control}) ai quali si aggiungono i seguenti: + \begin{errlist} + \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{errlist} +\end{prototype} + +Dato che la funzione \texttt{open} segue i link simbolici, è necessaria usare +un'altra funzione quando si vuole leggere il contenuto di un link simbolico, +questa funzione è la: - \begin{itemize} +\begin{prototype}{unistd.h} +{int readlink(const char * path, char * buff, size\_t size)} + Legge il contnuto del link simbolico indicato da \texttt{path} nel buffer + \texttt{buff} di dimensione \texttt{size}. Non chiude la stringa con un + carattere nullo e la tronca a \texttt{size} nel caso il buffer sia troppo + piccolo pe contenerla. + + + La funzione restituisce il numero di caratteri letti dentro \texttt{buff} o + -1 per un errore, in caso di errore. La variabile \texttt{errno} viene + settata secondo i codici di errore: + \begin{errlist} \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 è @@ -274,20 +444,49 @@ nell'header file \texttt{unistd.h}. 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} + \end{errlist} +\end{prototype} + + +\section{Il controllo di accesso ai file} +\label{sec:filedir_access_control} +\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{stiky}} +\label{sec:filedir_stiky} + +\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 alla funzioni il -programma deve includere il file \texttt{sys/stat.h}. +dell'analogo comando di shell \texttt{mkdir}; per accedere ai tipi usati +programma deve includere il file \texttt{sys/types.h}. -\begin{itemize} -\item \texttt{char * mkdir (const char * dirname, mode\_t mode)} - +\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. @@ -295,8 +494,8 @@ programma deve includere il file \texttt{sys/stat.h}. 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:filedir_access_control}) ai quali si aggiungono i seguenti: - \begin{itemize} + \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. @@ -310,8 +509,8 @@ programma deve includere il file \texttt{sys/stat.h}. 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} + \end{errlist} +\end{prototype} \subsection{Accesso alle directory} @@ -327,7 +526,7 @@ Per accedere al contenuto delle directory si usano i cosiddetti 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:fileintr_vfs}) in una opportuna struttura +parlavamo in \secref{sec:fileintr_vfs}) in una opportuna struttura \texttt{struct dirent}. @@ -347,11 +546,9 @@ 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}. +corrente. -\begin{itemize} -\item \texttt{char * getcwd (char * buffer, size\_t size)} - +\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 @@ -364,8 +561,7 @@ corrente. I prototipi di queste funzioni sono dichiarati in \texttt{unistd.h}. 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} + \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 @@ -373,14 +569,14 @@ corrente. I prototipi di queste funzioni sono dichiarati in \texttt{unistd.h}. \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} + \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 byters, vedi -\ref{sec:xxx_limits}; il problema è che in linux non esiste una dimensione +\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. @@ -396,40 +592,28 @@ 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)} - +\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 speficata dal pathname contenuto nella stringa \texttt{pathname}. +\end{prototype} -\item \texttt{int fchdir (int filedes)} analoga alla precedente, ma usa un - file descriptor invece del pathname. - +\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 - \ref{sec:filedir_access_control}) ai quali si aggiunge il codice + \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{itemize} - - - +\end{prototype} \section{La manipolazione delle caratteristiche dei files} \label{sec:filedir_infos} -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. - - \subsection{Le funzioni \texttt{stat}, \texttt{fstat} e \texttt{lstat}} \label{sec:filedir_stat} @@ -447,36 +631,10 @@ una convenzione. -\section{Il controllo di accesso ai file} -\label{sec:filedir_access_control} - - -\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{stiky}} -\label{sec:filedir_stiky} - -\subsection{Le funzioni \texttt{chown}, \texttt{fchown} e \texttt{lchown}} -\label{sec:filedir_chown} - - %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}). +%completo vedi \ntab), i permessi (vedi \secref{sec:file_perms}), le date (vedi +%\secref{sec:file_times}).