X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=filedir.tex;h=db9c352402dc45ab9846afe37bd79ca9fa471008;hp=e39d4c955a34d84bbabbd42533bfecb30751676b;hb=d99b4995b23505a9afde30adf3a716aa7a55f0e9;hpb=2edbeab14f348c4fa78f91e10066b74475c2353a diff --git a/filedir.tex b/filedir.tex index e39d4c9..db9c352 100644 --- a/filedir.tex +++ b/filedir.tex @@ -1,186 +1,712 @@ \chapter{Files e directories} \label{cha:files_and_dirs} -In questo capitolo tratteremo in dettaglio le varie caratteristiche di files e -directories, ed in particolare approfondiremo i dettagli su come è organizzata -la struttura dei files in un sistema unix, esamineremo come è strutturato il -sistema base di protezioni e controllo di accesso ai files, e tutta -l'interfaccia che permette la manipolazione dei vari attributi di files e -directories. Tutto quello che riguarda invece la manipolazione dei contenuti è -lasciato ai capitoli successivi. - - -\section{L'organizzazione di files e directories} -\label{sec:filedir_org} - -L'organizzazione dei nomi dei file deriva direttamente dall'organizzazione dei -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. +In questo capitolo tratteremo in dettaglio le modalità con cui si gestiscono +file e directory, ed in particolare esamineremo come è strutturato il sistema +base di protezioni e controllo di accesso ai file, e tutta l'interfaccia che +permette la manipolazione dei vari attributi di file e directory. Tutto quello +che riguarda invece la manipolazione del contenuto dei file è lasciato ai +capitoli successivi. -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 \secref{sec:xxx_chroot}) è la stessa per tutti i processi ed -equivale alla directory radice dell'albero (come descritto in -\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 \secref{sec:filedir_work_dir}) ed il pathname è -detto \textsl{relativo}. - -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{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 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 unix} -\label{sec:filedir_filesystem} - -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 -diversi, ognuno dei quali ha una sua particolare struttura e funzionalità -proprie; per questo non entreremo nei dettagli di un filesystem specifico, ma -daremo una descrizione a grandi linee che si adatta alle caratteristiche -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 a -disposizione per i dati e le directory. -\begin{figure}[htb] + +\section{Il controllo di accesso ai file} +\label{sec:filedir_access_control} + +Una delle caratteristiche fondamentali di tutti i sistemi unix-like è quella +del controllo di accesso ai file, che viene implementato per qualunque +filesystem standard. In questa sezione ne esamineremo i concetti essenziali e +le funzioni usate per gestirne i vari aspetti. + + +\subsection{I permessi per l'accesso ai file} +\label{sec:filedir_perm_overview} + +Il controllo di accesso ai file in unix segue un modello abbastanza semplice, +ma adatto alla gran parte delle esigenze, in cui si dividono i permessi su tre +livelli. Si tenga conto poi che quanto diremo è vero solo per filesystem di +tipo unix, e non è detto che sia applicabile a un filesystem +qualunque\footnote{ed infatti non è vero per il filesystem vfat di Windows, + per il quale vengono assegnati in maniera fissa con un opzione in fase di + montaggio}. 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 +identificatori di utenti e gruppi (\textsl{uid} e \textsl{gid}), e accessibili +da programm tramite i campi \var{st\_uid} e \var{st\_gid} della struttura +\var{stat} (si veda \secref{sec:filedir_stat}). Ad ogni file viene inoltre +associato un insieme di permessi che sono divisi in tre classi, e cioè +attribuiti rispettivamente all'utente proprietario del file, a un 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 +\textsl{w}, \textit{r} \textsl{x} nei comandi di sistema) applicabili +rispettivamente al proprietario, al gruppo, a tutti. I restanti tre bit +(\textsl{suid}, \textsl{sgid}, e \textsl{sticky}) sono usati per indicare +alcune caratteristiche più complesse su cui torneremo in seguito (vedi +\secref{sec:filedir_suid_sgid} e \secref{sec:filedir_sticky}). + +Anche i permessi sono tenuti per ciascun file (di qualunque tipo, quindi anche +per le fifo, i socket e i file di dispositivo) nell'inode, in opportuni bit +del campo \var{st\_mode} della struttura letta da \func{stat} (vedi +\figref{fig:filedir_stat_struct}). + + +In genere ci si riferisce a questi permessi usando le lettere \textsl{u} (per +\textit{user}), \textsl{g} (per \textit{group}) e \textsl{o} (per +\textit{other}), inoltre se si vuole indicare tutti questi gruppi insieme si +usa la lettera \textsl{a} (per \textit{all}). Si tenga ben presente questa +distinzione, dato che in certi casi, mutuando la termimologia in uso nel VMS, +si parla dei permessi base come di permessi di owner, group ed all, le cui +iniziali possono da luogo a confuzione. Le costanti che permettono di accedere +al valore numerico di questi bit sono riportate in \ntab. + +\begin{table}[htb] \centering + \footnotesize + \begin{tabular}[c]{|c|l|} + \hline + \var{st\_mode} bit & Significato \\ + \hline + \hline + \macro{S\_IRUSR} & \textit{user-read}, l'utente può leggere \\ + \macro{S\_IWUSR} & \textit{user-write}, l'utente può scrivere \\ + \macro{S\_IXUSR} & \textit{user-execute}, l'utente può eseguire \\ + \hline + \macro{S\_IRGRP} & \textit{group-read}, il gruppo può leggere \\ + \macro{S\_IWGRP} & \textit{group-write}, il gruppo può scrivere \\ + \macro{S\_IXGRP} & \textit{group-execute}, il gruppo può eseguire\\ + \hline + \macro{S\_IROTH} & \textit{other-read}, tutti possono leggere \\ + \macro{S\_IWOTH} & \textit{other-write}, tutti possono scrivere \\ + \macro{S\_IXOTH} & \textit{other-execute}, tutti possono eseguire\\ + \hline + \end{tabular} + \caption{I bit dei permessi di accesso ai file, come definiti in + \texttt{}} + \label{tab:file_bit_perm} +\end{table} + +Questi permessi vengono usati in maniera diversa dalle varie funzioni, e a +seconda che si riferiscano a file, link simbolici o directory, qui ci +limiteremo ad un riassunto delle regole generali, entrando nei +dettagli più avanti. + +La prima regola è che per poter accedere ad un file attraverso il suo pathname +occorre il permesso di esecuzione in ciascuna delle directory che compongono +il pathname, e lo stesso vale per aprire un file nella directory corrente (per +la quale appunto serve il diritto di esecuzione). + +Per una directory infatti il permesso di esecuzione ha il significato +specifico che essa può essere attraversata nella risoluzione del pathname, ed +è distinto dal permesso di lettura che invece implica che si può leggere il +contenuto della directory. Questo significa che se si ha il permesso di +esecuzione senza permesso di lettura si potrà lo stesso aprire un file in una +directory (se si hanno i permessi opportuni per il medesimo) ma non si potrà +vederlo con \cmd{ls} (per crearlo occorrerà anche il permesso di scrittura per +la directory). + +Il permesso di lettura per un file consente di aprirlo con le opzioni di sola +lettura (\macro{O\_RDONLY}) o di lettura-scrittura (\macro{O\_RDWR}) e +leggerne il contenuto. Il permesso di scrittura consente di aprire un file in +sola scrittura (\macro{O\_WRONLY}) o lettura-scrittura (\macro{O\_RDWR}) e +modificarne il contenuto, lo stesso permesso è necessario per poter troncare +il file con l'opzione \macro{O\_TRUNC}. + +Non si può creare un file fintanto che non si disponga del permesso di +esecuzione e di quello di scrittura per la directory di destinazione; gli +stessi permessi occorrono per cancellare un file da una directory (si ricordi +che questo non implica necessariamente la rimozione fisica del file), non è +necessario nessun tipo di permesso per il file stesso (infatti esso non viene +toccato, viene solo modificato il contenute della directory). + +Per poter eseguire un file (che sia un programma compilato od uno script di +shell), occorre il permesso di esecuzione per il medesimo, inoltre solo i file +regolari possono essere eseguiti. + +La procedura con cui il kernel stabilisce se un processo possiede un certo +permesso (di lettura, scrittura o esecuzione) si basa sul confronto fra +l'utente e il gruppo a cui il file appartiene (i valori di \var{st\_uid} e +\var{st\_gid} accennati in precedenza) e l'\textit{effective user id}, +l'\textit{effective group id} e gli eventuali \textit{supplementary group id} +del processo. + +Per una spiegazione dettagliata degli identificatori associati ai processi si +veda \secref{sec:prochand_perms}; normalmente, a parte quanto vedremo in +\secref{sec:filedir_suid_sgid}, l'\textit{effective user id} e +l'\textit{effective group id} corrispondono a uid e gid dell'utente che ha +lanciato il processo, mentre i \textit{supplementary group id} sono quelli dei +gruppi cui l'utente appartiene. + +% 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 +% a +% pertanto accesso senza restrizione a qualunque file del sistema. + +% In realtà il procedimento è più complesso di quanto descritto in maniera +% elementare qui; inoltre ad un processo sono associati diversi identificatori, +% torneremo su questo in maggiori dettagli in seguito in +% \secref{sec:proc_perms}. + +I passi attraverso i quali viene stabilito se il processo possiede il diritto +di accesso sono i seguenti: +\begin{itemize} +\item Se l'\textit{effective user id} del processo è zero (corrispondente + all'amministratore) l'accesso è sempre garantito senza nessun ulteriore + controllo. Per questo motivo \textsl{root} ha piena libertà di accesso a + tutti i file. +\item Se l'\textit{effective user id} del processo è uguale all'uid del + proprietario del file (nel qual caso si dice che il processo è proprietario + del file) allora: + \begin{itemize} + \item se il relativo\footnote{per relativo si intende il bit di user-read se + il processo, vuole accedere in scrittura, quello di user-write per + l'accesso in scrittura, etc.} bit dei permessi d'accesso dell'utente è + settato, l'accesso è consentito + \item altrimenti l'accesso è negato + \end{itemize} +\item Se l'\textit{effective group id} del processo o uno dei + \textit{supplementary group id} dei processi corrispondono al gid del file + allora: + \begin{itemize} + \item se il bit dei permessi d'accesso del gruppo è settato, l'accesso è + consentito, altrimenti l'accesso è negato + \end{itemize} +\item se il bit dei permessi d'accesso per tutti gli altri è settato, + l'accesso è consentito, altrimenti l'accesso è negato. +\end{itemize} + +Si tenga presente che questi passi vengono eseguiti esattamente in +quest'ordine. Questo vuol dire che se un processo è il proprietario di un file +l'accesso è consentito o negato solo sulla base dei permessi per l'utente; i +permessi per il gruppo non vengono neanche controllati; lo stesso vale se il +processo appartiene ad un gruppo appropriato, in questo caso i permessi per +tutti gli altri non vengono controllati. + +\subsection{I flag \texttt{suid} e \texttt{sgid}} +\label{sec:filedir_suid_sgid} + +Quandi si lancia un programma in genere l'\textit{effective user id} e +l'\textit{effective group id} sono settati rispettivamente all'uid e al gid +dell'utente che ha lanciato il programma. + + +Ma nei dodici bit del campo \var{st\_mode} relativi ai permessi esiste un bit +speciale, il \textit{set-user-ID bit} o suid, che se settato fa si che quando +un programma viene lanciato invece di avere assegnato come \textit{effective + user id} l'uid di chi lo lancia, assume quello del proprietario del file. +Analogamente il \textit{set-group-ID bit} o sgid settato per un file ha lo +stesso effetto sull'\textit{effective group id}. + +Questa caratteristica viene usata per permettere agli utenti normali di usare +programmi che abbisognano di privilegi speciali; l'esempio classico è il +comando \cmd{passwd} che ha la necessità di modificare il file delle password, +che può essere scritto solo dall'amministratore. Per questo il comando +\cmd{passwd} appartiene a root e ha il suid bit settato per cui quando viene +lanciato da un utente normale ha comunque i privilegi di root. + +Chiaramente avere un processo che ha privilegi superiori a quelli che avrebbe +normalmente un utente comporta vari rischi, e questo tipo di programmi devono +essere scritti accuratamente (torneremo sull'argomento in +\secref{sec:prochand_perms}). + +I due bit suid e sgid possono essere controllati all'interno di \var{st\_mode} +con l'uso delle due costanti \macro{S\_ISUID} e \macro{S\_ISGID}, definite in +\tabref{tab:filedir_file_mode_flags}. + + +\subsection{Il flag \texttt{sticky}} +\label{sec:filedir_sticky} + +L'ultimo + +\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{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 \secref{sec:file_perms}), le date (vedi +%\secref{sec:file_times}). + + + +\section{La manipolazione delle caratteristiche dei files} +\label{sec:filedir_infos} + +Come spiegato in \secref{sec:fileintr_filesystem} tutte le informazioni +generali relative alle caratteristiche di ciascun file sono mantenute +nell'inode. Vedremo in questa sezione come sia possibile accedervi usando la +funzione \texttt{stat} ed esamineremo alcune funzioni utilizzabili per +manipolare una parte di questa informazione. Tutto quello che invece riguarda +il meccanismo di controllo di accesso ad i file e le relative funzioni di +manipolazione sarà invece esaminanto in \secref{sec:filedir_access_control}. + + +\subsection{Le funzioni \texttt{stat}, \texttt{fstat} e \texttt{lstat}} +\label{sec:filedir_stat} + +La lettura delle informazioni relative ai file è fatta attraverso la famiglia +delle funzioni \func{stat}, che è la funzione che il comando \cmd{ls} usa +per poter stampare tutti i dati dei files. I prototipi di queste funzioni sono +i seguenti: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/stat.h} + \headdecl{unistd.h} + + \funcdecl{int stat(const char *file\_name, struct stat *buf)} Legge le + informazione del file specificato da \var{file\_name} e le inserisce in + \var{buf}. - \caption{Organizzazione dello spazio su un disco in partizioni e filesystem} - \label{fig:filedir_disk_filesys} -\end{figure} + \funcdecl{int lstat(const char *file\_name, struct stat *buf)} Identica a + \func{stat} eccetto che se il \var{file\_name} è un link simbolico vengono + lette le informazioni relativa ad esso e non al file a cui fa riferimento. + + \funcdecl{int fstat(int filedes, struct stat *buf)} Identica a \func{stat} + eccetto che si usa con un file aperto, specificato tramite il suo file + descriptor \var{filedes}. + + Le funzioni restituiscono zero in caso di successo e -1 per un errore, in + caso di errore \texttt{errno} viene settato ai valori: + \begin{errlist} + \item \texttt{EACCESS} non c'è il permesso di accedere al file. + \item \texttt{ENOTDIR} una componente del pathname non è una directory. + \item \texttt{EMLOOP} ci sono troppi link simbolici nel pathname. + \item \texttt{EFAULT} i puntatori usati sono fuori dallo spazio di indirizzi + del processo. + \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a + completare l'operazione. + \item \texttt{ENAMETOOLONG} il filename è troppo lungo. + \end{errlist} +\end{functions} -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] +La struttura \texttt{stat} è definita nell'header \texttt{sys/stat.h} e in +generale dipende dall'implementazione, la versione usata da Linux è mostrata +in \nfig, così come riportata dalla man page (in realtà la definizione +effettivamente usata nel kernel dipende dall'architettura e ha altri campi +riservati per estensioni come tempi più precisi, o per il padding dei campi). + +\begin{figure}[!htb] + \footnotesize \centering - - \caption{Organizzazione di un filesystem} - \label{fig:filedir_filesys_detail} + \begin{minipage}[c]{15cm} + \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} +struct stat { + dev_t st_dev; /* device */ + ino_t st_ino; /* inode */ + mode_t st_mode; /* protection */ + nlink_t st_nlink; /* number of hard links */ + uid_t st_uid; /* user ID of owner */ + gid_t st_gid; /* group ID of owner */ + dev_t st_rdev; /* device type (if inode device) */ + off_t st_size; /* total size, in bytes */ + unsigned long st_blksize; /* blocksize for filesystem I/O */ + unsigned long st_blocks; /* number of blocks allocated */ + time_t st_atime; /* time of last access */ + time_t st_mtime; /* time of last modification */ + time_t st_ctime; /* time of last change */ +}; + \end{lstlisting} + \end{minipage} + \normalsize + \caption{La struttura \texttt{stat} per la lettura delle informazioni dei + file} + \label{fig:filedir_stat_struct} \end{figure} -da questa figura si evidenziano 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: -\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'\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ù 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}. +Si noti come i vari membri della struttura siano specificati come tipi nativi +del sistema (di quelli definiti in \tabref{tab:xxx_sys_types}, e dichiarati in +\texttt{sys/types.h}). + + +\subsection{I tipi di file} +\label{sec:filedir_file_types} + +Come riportato in \tabref{tab:fileintr_file_types} in Linux oltre ai file e +alle directory esistono vari altri oggetti che possono stare su un filesystem; +il tipo di file è ritornato dalla \texttt{stat} nel campo \texttt{st\_mode}. + +Dato che il valore numerico può variare a seconda delle implementazioni, lo +standard POSIX definisce un insieme di macro per verificare il tipo di files, +queste vengono usate anche da Linux che supporta pure le estensioni per link +simbolici e socket definite da BSD, l'elenco completo di tutte le macro +definite in GNU/Linux è riportato in \ntab: +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|l|} + \hline + Macro & Tipo del file \\ + \hline + \hline + \macro{S\_ISREG(m)} & file regolare \\ + \macro{S\_ISDIR(m)} & directory \\ + \macro{S\_ISCHR(m)} & device a caraetteri \\ + \macro{S\_ISBLK(m)} & device a blocchi\\ + \macro{S\_ISFIFO(m)} & fifo \\ + \macro{S\_ISLNK(m)} & link simbolico \\ + \macro{S\_ISSOCK(m)} & socket \\ + \hline + \end{tabular} + \caption{Macro per i tipi di file (definite in \texttt{sys/stat.h})} + \label{tab:filedir_file_type_macro} +\end{table} + +Oltre a queste macro è possibile usare direttamente il valore di +\var{st\_mode} per ricavare il significato dei vari bit in esso memorizzati, +per questo sempre in \texttt{sys/stat.h} sono definiti i flag riportati in +\ntab: +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|c|l|} + \hline + Flag & Valore & Significato \\ + \hline + \hline + \macro{S\_IFMT} & 0170000 & bitmask per i bit del tipo di file \\ + \macro{S\_IFSOCK} & 0140000 & socket \\ + \macro{S\_IFLNK} & 0120000 & link simbolico \\ + \macro{S\_IFREG} & 0100000 & file regolare \\ + \macro{S\_IFBLK} & 0060000 & device a blocchi \\ + \macro{S\_IFDIR} & 0040000 & directory \\ + \macro{S\_IFCHR} & 0020000 & device a caratteri \\ + \macro{S\_IFIFO} & 0010000 & fifo \\ + \hline + \macro{S\_ISUID} & 0004000 & set UID bit \\ + \macro{S\_ISGID} & 0002000 & set GID bit \\ + \macro{S\_ISVTX} & 0001000 & sticky bit \\ + \hline + \macro{S\_IRWXU} & 00700 & bitmask per i permessi del proprietario \\ + \macro{S\_IRUSR} & 00400 & il proprietario ha permesso di lettura \\ + \macro{S\_IWUSR} & 00200 & il proprietario ha permesso di scrittura \\ + \macro{S\_IXUSR} & 00100 & il proprietario ha permesso di esecuzione\\ + \hline + \macro{S\_IRWXG} & 00070 & bitmask per i permessi del gruppo \\ + \macro{S\_IRGRP} & 00040 & il gruppo ha permesso di lettura \\ + \macro{S\_IWGRP} & 00020 & il gruppo ha permesso di scrittura \\ + \macro{S\_IXGRP} & 00010 & il gruppo ha permesso di esecuzione \\ + \hline + \macro{S\_IRWXO} & 00007 & bitmask per i permessi di tutti gli altri\\ + \macro{S\_IROTH} & 00004 & gli altri hanno permesso di lettura \\ + \macro{S\_IWOTH} & 00002 & gli altri hanno permesso di esecuzione \\ + \macro{S\_IXOTH} & 00001 & gli altri hanno permesso di esecuzione \\ + \hline + \end{tabular} + \caption{Costanti per l'identificazione dei vari bit che compongono il campo + \var{st\_mode} (definite in \texttt{sys/stat.h})} + \label{tab:filedir_file_mode_flags} +\end{table} + +Il primo valore definisce la maschera dei bit usati nei quali viene +memorizzato il tipo di files, mentre gli altri possono essere usati per +effettuare delle selezioni sul tipo di file voluto, combinando opportunamente +i vari flag; ad esempio se si volesse controllare se un file è una directory o +un file ordinario si potrebbe definire la condizione: +\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} +#define IS_FILE_DIR(x) (((x) & S_IFMT) & (S_IFDIR | S_IFREG)) +\end{lstlisting} +in cui prima si estraggono da \var{st\_mode} i bit relativi al tipo di file e +poi si effettua il confronto con la combinazione di tipi scelta. + +\subsection{La dimensione dei file} +\label{sec:filedir_file_size} + +Il membro \var{st\_size} contiene la dimensione del file in bytes (se il file +è un file normale, nel caso di un link simbolico al dimensione è quella del +pathname che contiene). + +Il campo \var{st\_blocks} definisce la lunghezza del file in blocchi di 512 +bytes. Il campo \var{st\_blksize} infine definisce la dimensione preferita per +i trasferimenti sui file (che è la dimensione usata anche dalle librerie del C +per l'interfaccia degli stream); scrivere sul file a blocchi di dati di +dimensione inferiore sarebbe inefficiente. + +Si tenga conto che lunghezza del file riportata in \var{st\_size} non è detto +che corrisponda all'occupazione dello spazio su disco per via della possibile +esistenza dei cosiddetti \textsl{buchi} (detti normalmente \textit{holes}) che +si formano tutte le volte che si va a scrivere su un file dopo aver eseguito +una \func{seek} (vedi \secref{sec:fileunix_lseek}) oltre la sua conclusione +corrente. + +In tal caso si avranno differenti risultati a seconda del modi in cui si +calcola la lunghezza del file, ad esempio il comando \cmd{du}, (che riporta il +numero di blocchi occupati) potrà dare una dimensione inferiore, mentre se si +legge dal file (ad esempio usando \cmd{wc -c}), dato che in tal caso per le +parti non scritte vengono restituiti degli zeri, si avrà lo stesso risultato +di \cmd{ls}. + +Se è sempre possibile allargare un file scrivendoci sopra od usando la +funzione \func{seek} per spostarsi oltre la sua fine. Esistono però anche casi +in cui si può avere bisogno di effettuare un troncamento scartando i dati al +di là della dimensione scelta come nuova fine del file. + +Un file può essere troncato a zero aprendolo con il flag \macro{O\_TRUNC}, ma +questo è un caso particolare; per qualunque altra dimensione si possono usare +le due funzioni: +\begin{functions} + \headdecl{unistd.h} \funcdecl{int truncate(const char *file\_name, off\_t + length)} Fa si che la dimensione del file \var{file\_name} sia troncata ad + un valore massimo specificato da \var{lenght}. -\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. + \funcdecl{int ftruncate(int fd, off\_t length))} Identica a \func{truncate} + eccetto che si usa con un file aperto, specificato tramite il suo file + descriptor \var{fd}, -\item Quando si cambia nome ad un file senza cambiare filesystem il contenuto - 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}). + Le funzioni restituiscono zero in caso di successo e -1 per un errore, in + caso di errore \texttt{errno} viene settato ai valori: + \begin{errlist} + \item \texttt{EACCESS} non c'è il permesso di accedere al file. + \item \texttt{ENOTDIR} una componente del pathname non è una directory. + \item \texttt{EMLOOP} ci sono troppi link simbolici nel pathname. + \item \texttt{EFAULT} i puntatori usati sono fuori dallo spazio di indirizzi + del processo. + \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a + completare l'operazione. + \item \texttt{ENOENT} il file non esiste. + \item \texttt{ENAMETOOLONG} il filename è troppo lungo. + \end{errlist} +\end{functions} + +Se il file è più lungo della lunghezza specificata i dati in eccesso saranno +perduti; il comportamento in caso di lunghezza inferiore non è specificato e +dipende dall'implementazione: il file può essere lasciato invariato o esteso +fino alla lunghezza scelta; in quest'ultimo caso lo spazio viene riempito con +zeri (e in genere si ha la creazione di un hole nel file). + + +\subsection{I tempi dei file} +\label{sec:filedir_file_times} -\end{enumerate} +Il sistema mantiene per ciascun file tre tempi. Questi sono registrati +nell'inode insieme agli altri attibuti del file e possono essere letti tramite +la funzione \func{stat}, che li restituisce attraverso tre campi della +struttura in \figref{fig:filedir_stat_struct}. Il significato di detti tempi e +dei relativi campi è riportato nello schema in \ntab: -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. +\begin{table}[htb] + \centering + \begin{tabular}[c]{|c|l|l|c|} + \hline + Membro & Significato & Funzione&opzione \\ + \hline + \hline + \var{st\_atime}& ultimo accesso ai dati del file &\func{read}& \cmd{-u}\\ + \var{st\_mtime}& ultima modifica ai dati del file &\func{write}& default\\ + \var{st\_ctime}& ultima modifica ai dati dell'inode&\func{chmod}, + \func{utime} & \cmd{-c} \\ + \hline + \end{tabular} + \caption{I tre tempi associati a ciascun file} + \label{tab:filedir_file_times} +\end{table} + +Il primo punto da tenere presente è la differenza fra il cosiddetto tempo di +modifica (il \textit{modification time} \var{st\_mtime}) e il tempo di +cambiamento di stato (il \textit{chage time} \var{st\_ctime}). Il primo +infatti fa riferimento ad una modifica del contenuto di un file, mentre il +secondo ad una modifica dell'inode; siccome esistono molte operazioni (come la +funzione \func{link} e molte altre che vedremo in seguito) che modificano solo +le informazioni contenute nell'inode senza toccare il file, diventa necessario +l'utilizzo di un altro tempo. + +Il sistema non tiene conto dell'ultimo accesso all'inode, pertanto funzioni +come \func{access} o \func{stat} non hanno alcuna influenza sui tre tempi. Il +tempo di ultimo accesso viene di solito usato per cancellare i file che non +servono più dopo un certo lasso di tempo (ad esempio \cmd{leafnode} cancella i +vecchi articoli sulla base di questo tempo). + +Il tempo di ultima modifica invece viene usato da \cmd{make} per decidere +quali file necessitano di essere ricompilati o (talvolta insieme anche al +tempo di cambiamento di stato) per decidere quali file devono essere +archiviati per il backup. Il comando \cmd{ls} (quando usato con le opzioni +\cmd{-l} o \cmd{-t}) mostra i tempi dei file secondo lo schema riportato +nell'ultima colonna di \curtab. + +L'effetto delle varie funzioni di manipolazione dei file sui tempi è +illustrato in \ntab. Si sono riportati gli effetti sia per il file a cui si fa +riferimento, sia per la directory che lo contiene; questi ultimi possono +essere capiti se si tiene conto di quanto già detto, e cioè che anche le +directory sono files, che il sistema tratta in maniera del tutto analoga agli +altri. + +Per questo motivo tutte le volte che compiremo una operazione su un file che +comporta una modifica della sua directory entry, andremo anche a scrivere +sulla directory che lo contiene cambiandone il tempo di modifica. Un esempio +di questo può essere la cancellazione di un file, mentre leggere o scrivere o +cambiarne i permessi ha effetti solo sui tempi del file. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|c|c|c|c|c|c|l|} + \hline + \multicolumn{1}{|c|}{Funzione} + &\multicolumn{3}{p{2cm}}{File o directory di riferimento} + &\multicolumn{3}{p{2cm}}{Directory genitrice del riferimento} + &\multicolumn{1}{|c|}{Note} \\ + \cline{2-7} + & \textsl{(a)} & \textsl{(m)}& \textsl{(c)} + & \textsl{(a)} & \textsl{(m)}& \textsl{(c)}& \\ + \hline + \hline + \func{chmod}, \func{fchmod} + & & &$\bullet$& & & & \\ + \func{chown}, \func{fchown} + & & &$\bullet$& & & & \\ + \func{creat} + &$\bullet$&$\bullet$&$\bullet$& &$\bullet$&$\bullet$& con + \macro{O\_CREATE} \\ \func{creat} + & &$\bullet$&$\bullet$& &$\bullet$&$\bullet$& + con \macro{O\_TRUNC} \\ \func{exec} + &$\bullet$& & & & & & \\ + \func{lchown} + & & &$\bullet$& & & & \\ + \func{link} + & & &$\bullet$& &$\bullet$&$\bullet$& \\ + \func{mkdir} + &$\bullet$&$\bullet$&$\bullet$& &$\bullet$&$\bullet$& \\ + \func{mkfifo} + &$\bullet$&$\bullet$&$\bullet$& &$\bullet$&$\bullet$& \\ + \func{open} + &$\bullet$&$\bullet$&$\bullet$& &$\bullet$&$\bullet$& con + \macro{O\_CREATE} \\ \func{open} + & &$\bullet$&$\bullet$& & & & con + \macro{O\_TRUNC} \\ \func{pipe} + &$\bullet$&$\bullet$&$\bullet$& & & & \\ + \func{read} + &$\bullet$& & & & & & \\ + \func{remove} + & & &$\bullet$& &$\bullet$&$\bullet$& using + \func{unlink}\\ \func{remove} + & & & & &$\bullet$&$\bullet$& using + \func{rmdir}\\ \func{rename} + & & &$\bullet$& &$\bullet$&$\bullet$& per entrambi + gli argomenti\\ \func{rmdir} + & & & & &$\bullet$&$\bullet$& \\ + \func{truncate}, \func{ftruncate} + & &$\bullet$&$\bullet$& & & & \\ + \func{unlink} + & & &$\bullet$& &$\bullet$&$\bullet$& \\ + \func{utime} + &$\bullet$&$\bullet$&$\bullet$& & & & \\ + \func{write} + & &$\bullet$&$\bullet$& & & & \\ + \hline + \end{tabular} + \caption{Effetti delle varie funzioni su tempi di ultimo accesso + \textsl{(a)}, ultima modifica \textsl{(m)} e ultimo cambiamento + \textsl{(c)}} + \label{tab:filedir_times_effects} +\end{table} + +Si noti infine come \var{st\_ctime} non abbia nulla a che fare con il tempo di +creazione del file, usato da molti altri sistemi operativi, che in unix non +esiste. + + +\subsection{La funzione \texttt{utime}} +\label{sec:filedir_utime} -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 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 voce \texttt{..} di \texttt{textdir}. +I tempi di ultimo accesso e modifica possono essere cambiati usando la +funzione \func{utime}, il cui prototipo è: + +\begin{prototype}{utime.h} +{int utime(const char * filename, struct utimbuf *times)} + +Cambia i tempi di ultimo accesso e modifica dell'inode specificato da +\var{filename} secondo i campi \var{actime} e \var{modtime} di \var{times}. Se +questa è \macro{NULL} allora viene usato il tempo corrente. + +La funzione restituisce zero in caso di successo e -1 in caso di errore, nel +qual caso \var{errno} è settata opportunamente. +\begin{errlist} +\item \texttt{EACCESS} non si ha il permesso di scrittura sul file. +\item \texttt{ENOENT} \var{filename} non esiste. +\end{errlist} +\end{prototype} + +La struttura \var{utimebuf} usata da \func{utime} è definita come: +\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} +struct utimbuf { + time_t actime; /* access time */ + time_t modtime; /* modification time */ +}; +\end{lstlisting} + +L'effetto della funzione e i privilegi necessari per eseguirla dipendono da +cosa è l'argomento \var{times}; se è \textit{NULL} la funzione setta il tempo +corrente ed è sufficiente avere accesso in scrittura al file; se invece si è +specificato un valore la funzione avrà successo solo se si è proprietari del +file (o si hanno i privilegi di amministratore). + +Si tenga presente che non è comunque possibile specificare il tempo di +cambiamento di stato del file, che viene comunque cambiato dal kernel tutte le +volte che si modifica l'inode (quindi anche alla chiamata di \func{utime}). +Questo serve anche come misura di sicurezza per evitare che si possa +modificare un file nascondendo completamente le proprie tracce. In realtà la +cosa resta possibile, se si è in grado di accedere al device, scrivendo +direttamente sul disco senza passare attraverso il filesystem, ma ovviamente è +molto più complicato da realizzare. + + + + + + +\section{La manipolazione di file e directory} + +Come già accennato in \secref{sec:fileintr_filesystem} in un sistema unix-like +i file hanno delle caratteristiche specifiche dipendenti dall'architettura del +sistema, esamineremo qui allora le funzioni usate per la creazione di link +simbolici e diretti e per la gestione delle directory, approfondendo quanto +già accennato in precedenza. \subsection{Le funzioni \texttt{link} e \texttt{unlink}} -\label{sec:filedir_link} +\label{sec:fileintr_link} -Una delle caratteristiche usate quando si opera con i file è quella di poter +Una delle caratteristiche comuni a vari sistemi operativi è 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 è 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. +Come spiegato in \secref{sec:fileintr_architecture} 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 @@ -191,61 +717,43 @@ principali, come risultano dalla man page, sono le seguenti: 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 seguenti - codici di errore: + La funzione restituisce zero in caso di successo e -1 in caso di errore. La + variabile \texttt{errno} viene settata opportunamente, i principali codici + di errore sono: \begin{errlist} \item \texttt{EXDEV} \texttt{oldpath} e \texttt{newpath} non sono sullo stesso filesystem. \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. + \texttt{newpath} non supporta i link diretti o è una directory. \item \texttt{EEXIST} un file (o una directory) con quel nome esiste di già. \item \texttt{EMLINK} ci sono troppi link al file \texttt{oldpath} (il numero massimo è specificato dalla variabile \texttt{LINK\_MAX}, vedi \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. +ma si limita ad aumentare di uno il numero di referenze al file (come si può +controllare con il campo \var{st\_nlink} di \var{stat}) 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 +Per quanto dicevamo in \secref{sec:fileintr_filesystem} la creazione del collegamento diretto è possibile solo se entrambi i pathname sono nello stesso filesystem; 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}. +in alcuni filesystem 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:fileintr_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 generale nei filesystem usati 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: @@ -261,25 +769,14 @@ effettua con la funzione \texttt{unlink}; il suo prototipo 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. + \item \texttt{EISDIR} \var{pathname} si riferisce ad una directory + (valore specifico ritornato da linux che non consente l'uso di + \texttt{unlink} con le directory, e non conforme allo standard POSIX, che + prescrive invece l'uso di \texttt{EPERM} in caso l'operazione non sia + consnetita o il processo non abbia privilegi sufficienti). + \item \texttt{EROFS} \var{pathname} è su un filesystem montato in sola + lettura. + \item \texttt{EISDIR} \var{pathname} fa riferimento a una directory. \end{errlist} \end{prototype} @@ -307,7 +804,7 @@ crash dei programmi; la tecnica \texttt{unlink} subito dopo. \subsection{Le funzioni \texttt{remove} e \texttt{rename}} -\label{sec:filedir_cre_canc} +\label{sec:fileintr_remove} 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 @@ -340,35 +837,48 @@ nuovo nome dopo che il vecchio 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{EISDIR} \texttt{newpath} è una directory già esistente mentre + \texttt{oldpath} non è una directory. + \item \texttt{EXDEV} \texttt{oldpath} e \texttt{newpath} non sono sullo + stesso filesystem. + \item \texttt{ENOTEMPTY} \texttt{newpath} è una directory già esistente e + non vuota. + \item \texttt{EBUSY} o \texttt{oldpath} o \texttt{newpath} sono in uso da + parte di qualche processo (come directory di lavoro o come root) o del + sistema (come mount point). + \item \texttt{EINVAL} \texttt{newpath} contiene un prefisso di + \texttt{oldpath} o più in generale si è cercato di creare una directory + come sottodirectory di se stessa. + \item \texttt{EMLINK} \texttt{oldpath} ha già il massimo numero di link + consentiti o è una directory e la directory che contiene \texttt{newpath} + ha già il massimo numero di link. + \item \texttt{ENOTDIR} Uno dei componenti dei pathname non è una directory + o\texttt{oldpath} è una directory e \texttt{newpath} esiste e non è una + directory. + \item \texttt{EFAULT} o \texttt{oldpath} o \texttt{newpath} è 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{EPERM} le directory contenenti \texttt{oldpath} o + \texttt{newpath} hanno lo sticky bit attivo e i permessi del processo non + consentono rispettivamente la cancellazione e la creazione del file, o il + filesystem non supporta i link. + \item \texttt{ENAMETOOLONG} uno dei 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} il kernel non ha a disposizione memoria sufficiente a completare l'operazione. + \item \texttt{EROFS} I file sono su un filesystem montato in sola lettura. \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} - + \item \texttt{ENOSPC} Il device di destinazione non ha più spazio per la + nuova voce. \end{errlist} \end{prototype} \subsection{I link simbolici} -\label{sec:filedir_sym_link} +\label{sec:fileintr_symlink} Siccome la funzione \texttt{link} crea riferimenti agli inodes, essa può funzionare soltanto per file che risiedono sullo stesso filesystem, dato che @@ -388,10 +898,10 @@ 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. +o rinominare i file operano direttamente sul link simbolico (per l'elenco vedi +\ntab). 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 simbolici sono le seguenti, esse sono tutte dichiarate nell'header file \texttt{unistd.h}. @@ -443,86 +953,86 @@ questa funzione \end{errlist} \end{prototype} +In \ntab\ si è riportato un elenco dei comportamenti delle varie funzioni che +operano sui file rispetto ai link simbolici; specificando quali seguono il +link simbolico e quali possono operare direttamente sul suo contenuto. +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|c|c|} + \hline + Funzione & Segue il link & Non segue il link \\ + \hline + \hline + \func{access} & $\bullet$ & \\ + \func{chdir} & $\bullet$ & \\ + \func{chmod} & $\bullet$ & \\ + \func{chown} & & $\bullet$ \\ + \func{creat} & $\bullet$ & \\ + \func{exec} & $\bullet$ & \\ + \func{lchown} & $\bullet$ & $\bullet$ \\ + \func{link} & & \\ + \func{lstat} & & $\bullet$ \\ + \func{mkdir} & $\bullet$ & \\ + \func{mkfifo} & $\bullet$ & \\ + \func{mknod} & $\bullet$ & \\ + \func{open} & $\bullet$ & \\ + \func{opendir} & $\bullet$ & \\ + \func{pathconf} & $\bullet$ & \\ + \func{readlink} & & $\bullet$ \\ + \func{remove} & & $\bullet$ \\ + \func{rename} & & $\bullet$ \\ + \func{stat} & $\bullet$ & \\ + \func{truncate} & $\bullet$ & \\ + \func{unlink} & & $\bullet$ \\ + \hline + \end{tabular} + \caption{Uso dei link simbolici da parte di alcune funzioni.} + \label{tab:filedir_symb_effect} +\end{table} +si noti che non si è specificato il comportamento delle funzioni che operano +con i file descriptor, in quanto la gestione del link simbolico viene in +genere effttuata dalla funzione che restituisce il file descriptor +(normalmente la \func{open}). -\section{La manipolazione delle caratteristiche dei files} -\label{sec:filedir_infos} - -Come spiegato in \secref{sec:filedir_file_handling} tutte le informazioni -generali relative alle caratteristiche di ciascun file sono mantenute -nell'inode. Vedremo in questa sezione come sia possibile accedervi usando la -funzione \texttt{stat} ed esamineremo alcune funzioni utilizzabili per -manipolare una parte di questa informazione. Tutto quello che invece riguarda -il meccanismo di controllo di accesso ad i file e le relative funzioni di -manipolazione sarà invece esaminanto in \secref{sec:filedir_access_control}. - - -\subsection{Le funzioni \texttt{stat}, \texttt{fstat} e \texttt{lstat}} -\label{sec:filedir_stat} - -La lettura delle informazioni relative ai file è fatta attraverso la famiglia -delle funzioni \texttt{stat}, questa è la funzione che il comando \texttt{ls} -usa per poter stampare tutti i dati dei files; il prototipo della funzione è -il seguente; -\begin{prototype}{sys/stat.h} -{int stat(const char *file\_name, struct stat *buf)} - - La funzione restituisce zero in caso di successo e -1 per un errore, in caso - di errore \texttt{errno} viene settato ai valori: - \begin{errlist} - \item \texttt{EACCESS} Non c'è il permesso di accedere al file. - \item \texttt{ENOTDIR} Una componente del pathname non è una directory. - \item \texttt{EMLOOP} Ci sono troppi link simbolici nel pathname. - \item \texttt{EFAULT} I puntatori usati sono fuori dallo spazio di indirizzi - del processo. - \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a - completare l'operazione. - \item \texttt{ENAMETOOLONG} Il filename è troppo lungo. - \end{errlist} -\end{prototype} - -\subsection{I tipi di file} -\label{sec:filedir_file_types} - -\subsection{La dimensione dei file} -\label{sec:filedir_file_size} - -\subsection{I tempi dei file} -\label{sec:filedir_file_times} - -\subsection{La funzione \texttt{utime}} -\label{sec:filedir_utime} - - - - -\section{Il controllo di accesso ai file} -\label{sec:filedir_access_control} - - -\subsection{I flag \texttt{suid} e \texttt{sgid}} -\label{sec:filedir_suid_sgid} - -\subsection{La titolarità di nuovi files e directory} -\label{sec:filedir_ownership} - -\subsection{La funzione \texttt{access}} -\label{sec:filedir_access} - -\subsection{La funzione \texttt{umask}} -\label{sec:filedir_umask} - -\subsection{Le funzioni \texttt{chmod} e \texttt{fchmod}} -\label{sec:filedir_chmod} - -\subsection{Il flag \texttt{sticky}} -\label{sec:filedir_sticky} - -\subsection{Le funzioni \texttt{chown}, \texttt{fchown} e \texttt{lchown}} -\label{sec:filedir_chown} +\begin{figure}[htb] + \centering + \includegraphics[width=5cm]{img/link_loop.eps} + \caption{Esempio di loop nel filesystem creato con un link simbolico.} + \label{fig:filedir_link_loop} +\end{figure} +Un caso comune che si può avere con i link simbolici è la creazione dei +cosiddetti \textit{loop}. La situazione è illustrata in \curfig, che riporta +la struttura della directory \file{/boot}. Come si vede si è creato al suo +interno un link simbolico che punta di nuovo a \file{/boot}\footnote{Questo + tipo di loop è stato effettuato per poter permettere a \cmd{grub} (un + bootloader estremamente avanzato in grado di accedere direttamente + attraverso vari filesystem al file da lanciare come sistema operativo) di + vedere i file in questa directory, che è montata su una partizione separata + (e che grub vedrebbe come radice), con lo stesso path con cui verrebbero + visti dal sistema operativo.}. + +Questo può causare problemi per tutti quei programmi che effettuassero uno +scan di una directory senza tener conto dei link simbolici, in quel caso +infatti il loop nella directory + +Un secondo punto da tenere presente è che un link simbolico può essere fatto +anche ad un file che non esiste; ad esempio possiamo creare un file temporaneo +nella nostra directory con un link del tipo: +\begin{verbatim} +$ln -s /tmp/tmp_file temporaneo +\end{verbatim}%$ +ma anche se \file{/tmp/tmp\_file} non esiste. Aprendo in scrittura +\file{temporaneo} questo verrà scritto; ma se cercassimo di accederlo in sola +lettura (ad esempio con \cmd{cat}) otterremmo: +\begin{verbatim} +$ cat prova +cat: prova: No such file or directory +\end{verbatim}%$ +con un errore che sembra sbagliato, dato \cmd{ls} ci mostrerebbe l'esistenza +di \file{temporaneo}. -\section{La manipolazione delle directories} -\label{sec:filedir_dir_handling} \subsection{Le funzioni \texttt{mkdir} e \texttt{rmdir}} \label{sec:filedir_dir_creat_rem} @@ -646,7 +1156,7 @@ per cambiare directory di lavoro. \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 @@ -656,11 +1166,3 @@ per cambiare directory di lavoro. \end{prototype} - - -%La struttura fondamentale che contiene i dati essenziali relativi ai file è il -%cosiddetto \textit{inode}; questo conterrà informazioni come il -%tipo di file (file di dispositivo, directory, file di dati, per un elenco -%completo vedi \ntab), i permessi (vedi \secref{sec:file_perms}), le date (vedi -%\secref{sec:file_times}). -