Ad ogni file unix associa sempre l'utente che ne è proprietario (il cosiddetto
\textit{owner}) e il gruppo di appartenenza, secondo il meccanismo degli
-identificatoti di utenti e gruppi (uid e gig) già accennato in
-\secref{sec:intro_multiuser}, e un insieme di permessi che sono divisi in tre
-classi, e cioè attribuiti rispettivamente al proprietario, a qualunque utente
-faccia parte del gruppo cui appartiene il file, e a tutti gli altri utenti.
+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
-\textit{w}, \textit{r} \textit{x} nell'output di \cmd{ls}) applicabili
-rispettivamente al proprietario, al gruppo, a tutti (una descrizione più
-dettagliata dei vari permessi associati ai file è riportata in
-\secref{sec:filedir_suid_sgid}). I restanti tre bit sono usati per indicare
-alcune caratteristiche più complesse (\textit{suid}, \textit{sgid}, e
-\textit{sticky}) su cui pure torneremo in seguito (vedi
+\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}).
-Tutte queste informazioni sono tenute per ciascun file nell'inode, in
-opportuni bit del campo \var{st\_mode} della struttura letta da \func{stat}
-(vedi \figref{fig:filedir_stat_struct}) che possono essere controllati con i
-valori riportati in \ntab.
+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
\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 \\
+ \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\_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{<sys/stat.h>}}
\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.
+
+
+Per stabilire se un processo possiede un certo permesso ogni volta che si
+apre, crea o cancella un file il kernel esegue una serie di controlli
+guardando utente e gruppo a cui il file appartiene (i valori di \var{st\_uid}
+e \var{st\_gid}) che confronta con l'\textit{effective user id},
+\textit{effective group id} e gli eventuali \textit{supplementary group id}
+del processo (per una spiegazione dettagliata degli ID dei processi si veda
+\secref{sec:prochand_perms}; normalmente, a parte quanto spiegato in
+\secref{sec:filedir_suid_sgid}, essi corrispondo all'uid e al gid dell'utente
+che ha lanciato il processo).
+
+
+
+
% 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
+\section{La manipolazione delle caratteristiche dei files}
+\label{sec:filedir_infos}
-\section{La manipolazione di file e directory}
-
-Le prime funzioni che considereremo sono quelle relative alla gestione di file
-e directory, secondo le caratteristiche standard che essi presentano in un
-filesystem unix, la cui struttura abbiamo esaminato in precedenza (vedi
-\secref{sec:fileintr_filesystem}).
+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{link} e \texttt{unlink}}
-\label{sec:fileintr_link}
-Una delle caratteristiche usate quando si opera con i file è quella di poter
-creare dei nomi fittizi (alias o collegamenti) per potersi riferire allo
-stesso file accedendovi da directory diverse. Questo è possibile anche in
-ambiente unix, dove tali collegamenti sono usualmente chiamati \textit{link},
-ma data la struttura del sistema ci sono due metodi sostanzialmente diversi
-per fare questa operazione.
+\subsection{Le funzioni \texttt{stat}, \texttt{fstat} e \texttt{lstat}}
+\label{sec:filedir_stat}
-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.
+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}
-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}). Il prototipo della funzione e le sue caratteristiche
-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}.
+ \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}.
- 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 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}).
- \end{errlist}
+ \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.
-\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: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,
-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:
-
-\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.
+ \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}.
- 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:
+ 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{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.
+ \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}
-
-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).
+\end{functions}
-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.
+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).
-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.
+\begin{figure}[!htb]
+ \footnotesize
+ \centering
+ \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}
-\subsection{Le funzioni \texttt{remove} e \texttt{rename}}
-\label{sec:fileintr_remove}
+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}).
-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}
+\subsection{I tipi di file}
+\label{sec:filedir_file_types}
-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.
+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}.
-\begin{prototype}{stdio.h}
-{int rename(const char *oldpath, const char *newpath)}
- Rinomina un file, spostandolo fra directory diverse quando richiesto.
+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 venfono usate anche da Linux che supporta pure le estensioni per link
+simbolici e socket definite da BDS, l'elenco è 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 normale \\
+ \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}
- 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{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} 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{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{ENOSPC} Il device di destinazione non ha più spazio per la
- nuova voce.
- \end{errlist}
-\end{prototype}
+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 for the file type bitfields \\
+ \macro{S\_IFSOCK} & 0140000 & socket \\
+ \macro{S\_IFLNK} & 0120000 & symbolic link \\
+ \macro{S\_IFREG} & 0100000 & regular file \\
+ \macro{S\_IFBLK} & 0060000 & block device \\
+ \macro{S\_IFDIR} & 0040000 & directory \\
+ \macro{S\_IFCHR} & 0020000 & character device \\
+ \macro{S\_IFIFO} & 0010000 & fifo \\
+ \macro{S\_ISUID} & 0004000 & set UID bit \\
+ \macro{S\_ISGID} & 0002000 & set GID bit (see below) \\
+ \macro{S\_ISVTX} & 0001000 & sticky bit (see below) \\
+ \macro{S\_IRWXU} & 00700 & mask for file owner permissions \\
+ \macro{S\_IRUSR} & 00400 & owner has read permission \\
+ \macro{S\_IWUSR} & 00200 & owner has write permission \\
+ \macro{S\_IXUSR} & 00100 & owner has execute permission \\
+ \macro{S\_IRWXG} & 00070 & mask for group permissions \\
+ \macro{S\_IRGRP} & 00040 & group has read permission \\
+ \macro{S\_IWGRP} & 00020 & group has write permission \\
+ \macro{S\_IXGRP} & 00010 & group has execute permission \\
+ \macro{S\_IRWXO} & 00007 & mask for permissions for others (not in
+ group) \\
+ \macro{S\_IROTH} & 00004 & others have read permission \\
+ \macro{S\_IWOTH} & 00002 & others have write permisson \\
+ \macro{S\_IXOTH} & 00001 & others have execute permission \\
+ \hline
+ \end{tabular}
+ \caption{Flag per il campo \var{st\_mode} (definite in
+ \texttt{sys/stat.h})}
+ \label{tab:filedir_file_mode_flags}
+\end{table}
-\subsection{I link simbolici}
-\label{sec:fileintr_symlink}
+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.
-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.
+\subsection{La dimensione dei file}
+\label{sec:filedir_file_size}
-Per ovviare a queste limitazioni i sistemi unix supportano un'altra forma di
-link (i cosiddetti \textit{soft link} o \textit{symbolic link}), che sono,
-come avviene in altri sistemi operativi, dei file che contengono il
-semplicemente il riferimento ad un altro file (o directory). In questo modo è
-possibile effettuare link anche attraverso filesystem diversi e a directory, e
-pure a file che non esistono ancora.
+Il 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 sistema funziona in quanto i link simbolici sono contrassegnati come tali
-al kernel (analogamente a quanto avviene per le directory) per cui la chiamata
-ad una \texttt{open} o una \texttt{stat} su un link simbolico comporta la
-lettura del contenuto del medesimo e l'applicazione della funzione al file
-specificato da quest'ultimo. Invece altre funzioni come quelle per cancellare
-o rinominare i file operano direttamente sul link simbolico (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.
+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.
-Le funzioni per operare sui link simbolici sono le seguenti, esse sono tutte
-dichiarate nell'header file \texttt{unistd.h}.
+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.
-\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
- \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}
+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}.
-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:
+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.
-\begin{prototype}{unistd.h}
-{int readlink(const char * path, char * buff, size\_t size)}
- Legge il contenuto 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 per contenerla.
+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}.
- 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:
+ \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},
+
+ 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{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}.
+ \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{prototype}
+\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}
+
+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:
-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|}
+ \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
- 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}
+ \caption{I tre tempi associati a ciascun file}
+ \label{tab:filedir_file_times}
\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}).
-\begin{figure}[htb]
+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
- \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}
+ \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}
-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.}.
+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.
-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}.
+\subsection{La funzione \texttt{utime}}
+\label{sec:filedir_utime}
+I tempi di ultimo accesso e modifica possono essere cambiati usando la
+funzione \func{utime}, il cui prototipo è:
-\subsection{Le funzioni \texttt{mkdir} e \texttt{rmdir}}
-\label{sec:filedir_dir_creat_rem}
+\begin{prototype}{utime.h}
+{int utime(const char * filename, struct utimbuf *times)}
-Per creare una nuova directory si può usare la seguente funzione, omonima
-dell'analogo comando di shell \texttt{mkdir}; per accedere ai tipi usati
-programma deve includere il file \texttt{sys/types.h}.
+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.
-\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.
-
- 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
- \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.
- \item \texttt{EEXIST} Un file (o una directory) con quel nome esiste di già.
- \item \texttt{EMLINK} La directory in cui si vuole creare la nuova directory
- contiene troppi file. Sotto Linux questo normalmente non avviene perché il
- filesystem standard consente la creazione di un numero di file maggiore di
- quelli che possono essere contenuti nell'hard-disk, ma potendo avere a che
- fare anche con filesystem di altri sistemi questo errore può presentarsi.
- \item \texttt{ENOSPC} Non c'è abbastanza spazio sul file system per creare
- la nuova directory.
- \item \texttt{EROFS} La directory su cui si vuole inserire la nuova
- directory è su un filesystem montato readonly.
- \end{errlist}
+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}
-\subsection{Accesso alle directory}
-\label{sec:filedir_dir_read}
+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).
-Benché le directory siano oggetti del filesystem come tutti gli altri non ha
-ovviamente senso aprirle come fossero dei file di dati. Può però essere utile
-poterne leggere il contenuto ad esempio per fare la lista dei file che esse
-contengono o ricerche sui medesimi.
+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.
-Per accedere al contenuto delle directory si usano i cosiddetti
-\textit{directory streams} (chiamati così per l'analogia con i file stream);
-la funzione \texttt{opendir} apre uno di questi stream e la funzione
-\texttt{readdir} legge il contenuto della directory, i cui elementi sono le
-\textit{directory entries} (da distinguersi da quelle della cache di cui
-parlavamo in \secref{sec:fileintr_vfs}) in una opportuna struttura
-\texttt{struct dirent}.
-\subsection{La directory di lavoro}
-\label{sec:filedir_work_dir}
-A ciascun processo è associato ad una directory nel filesystem che è chiamata
-directory corrente o directory di lavoro (\textit{current working directory})
-che è quella a cui si fa riferimento quando un filename è espresso in forma
-relativa (relativa appunto a questa directory).
-Quando un utente effettua il login questa directory viene settata alla
-cosiddetta \textit{home directory} del suo account, il comando \texttt{cd}
-della shell consente di cambiarla a piacere, spostandosi da una directory ad
-un'altra. Siccome la directory corrente resta la stessa quando viene creato
-un processo figlio, la directory corrente della shell diventa anche la
-directory corrente di qualunque comando da essa lanciato.
-Le funzioni qui descritte servono esaminare e cambiare la directory di lavoro
-corrente.
+\section{La manipolazione di file e directory}
-\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
- specificare un puntatore nullo come \textit{buffer}, nel qual caso la
- stringa sarà allocata automaticamente per una dimensione pari a
- \texttt{size} qualora questa sia diversa da zero, o della lunghezza esatta
- del pathname altrimenti. In questo caso si deve ricordare di disallocare la
- stringa una volta cessato il suo utilizzo.
-
- La funzione restituisce il puntatore \texttt{buffer} se riesce,
- \texttt{NULL} se fallisce, in quest'ultimo caso la variabile
- \texttt{errno} è settata con i seguenti codici di errore:
- \begin{errlist}
- \item \texttt{EINVAL} L'argomento \texttt{size} è zero e \texttt{buffer} non
- è nullo.
- \item \texttt{ERANGE} L'argomento \texttt{size} è più piccolo della
- lunghezza del pathname.
- \item \texttt{EACCESS} Manca il permesso di lettura o di ricerca su uno dei
- componenti del pathname (cioè su una delle directory superiori alla
- corrente).
- \end{errlist}
-\end{prototype}
+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.
-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 bytes, vedi
-\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.
-Una seconda funzione simile è \texttt{char * get\_current\_dir\_name(void)}
-che è sostanzialmente equivalente ad una \texttt{getcwd(NULL, 0)}, con la sola
-differenza che essa ritorna il valore della variabile di ambiente
-\texttt{PWD}, che essendo costruita dalla shell può contenere anche dei
-riferimenti simbolici.
+\subsection{Le funzioni \texttt{link} e \texttt{unlink}}
+\label{sec:fileintr_link}
-Come già detto in unix anche le directory sono file, è possibile pertanto
-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.
+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.
-\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 specificata dal pathname
- contenuto nella stringa \texttt{pathname}.
-\end{prototype}
-
-\begin{prototype}{unistd.h}{int fchdir (int filedes)}
- Analoga alla precedente, ma usa un file descriptor invece del pathname.
+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.
- 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
- \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.
+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}). Il prototipo della funzione e le sue caratteristiche
+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 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 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}).
+ \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 (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: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,
+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}.
-\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}
+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:
- \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}.
-
- \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}.
+\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.
- Le funzioni restituiscono zero in caso di successo e -1 per un errore, in
- caso di errore \texttt{errno} viene settato ai valori:
+ 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} 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.
+ \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{functions}
+\end{prototype}
-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).
+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).
-\begin{figure}[!htb]
- \footnotesize
- \centering
- \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}
+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 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}).
+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:fileintr_remove}
-\subsection{I tipi di file}
-\label{sec:filedir_file_types}
+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}:
-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}.
+\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}
-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 venfono usate anche da Linux che supporta pure le estensioni per link
-simbolici e socket definite da BDS, l'elenco è 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 normale \\
- \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}
+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.
-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 for the file type bitfields \\
- \macro{S\_IFSOCK} & 0140000 & socket \\
- \macro{S\_IFLNK} & 0120000 & symbolic link \\
- \macro{S\_IFREG} & 0100000 & regular file \\
- \macro{S\_IFBLK} & 0060000 & block device \\
- \macro{S\_IFDIR} & 0040000 & directory \\
- \macro{S\_IFCHR} & 0020000 & character device \\
- \macro{S\_IFIFO} & 0010000 & fifo \\
- \macro{S\_ISUID} & 0004000 & set UID bit \\
- \macro{S\_ISGID} & 0002000 & set GID bit (see below) \\
- \macro{S\_ISVTX} & 0001000 & sticky bit (see below) \\
- \macro{S\_IRWXU} & 00700 & mask for file owner permissions \\
- \macro{S\_IRUSR} & 00400 & owner has read permission \\
- \macro{S\_IWUSR} & 00200 & owner has write permission \\
- \macro{S\_IXUSR} & 00100 & owner has execute permission \\
- \macro{S\_IRWXG} & 00070 & mask for group permissions \\
- \macro{S\_IRGRP} & 00040 & group has read permission \\
- \macro{S\_IWGRP} & 00020 & group has write permission \\
- \macro{S\_IXGRP} & 00010 & group has execute permission \\
- \macro{S\_IRWXO} & 00007 & mask for permissions for others (not in
- group) \\
- \macro{S\_IROTH} & 00004 & others have read permission \\
- \macro{S\_IWOTH} & 00002 & others have write permisson \\
- \macro{S\_IXOTH} & 00001 & others have execute permission \\
- \hline
- \end{tabular}
- \caption{Flag per 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.
+\begin{prototype}{stdio.h}
+{int rename(const char *oldpath, const char *newpath)}
+ Rinomina un file, spostandolo fra directory diverse quando richiesto.
-\subsection{La dimensione dei file}
-\label{sec:filedir_file_size}
+ 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{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} 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{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{ENOSPC} Il device di destinazione non ha più spazio per la
+ nuova voce.
+ \end{errlist}
+\end{prototype}
-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).
+\subsection{I link simbolici}
+\label{sec:fileintr_symlink}
-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.
+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.
-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.
+Per ovviare a queste limitazioni i sistemi unix supportano un'altra forma di
+link (i cosiddetti \textit{soft link} o \textit{symbolic link}), che sono,
+come avviene in altri sistemi operativi, dei file che contengono il
+semplicemente il riferimento ad un altro file (o directory). In questo modo è
+possibile effettuare link anche attraverso filesystem diversi e a directory, e
+pure a file che non esistono ancora.
-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}.
+Il sistema funziona in quanto i link simbolici sono contrassegnati come tali
+al kernel (analogamente a quanto avviene per le directory) per cui la chiamata
+ad una \texttt{open} o una \texttt{stat} su un link simbolico comporta la
+lettura del contenuto del medesimo e l'applicazione della funzione al file
+specificato da quest'ultimo. Invece altre funzioni come quelle per cancellare
+o rinominare i file operano direttamente sul link simbolico (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.
-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.
+Le funzioni per operare sui link simbolici sono le seguenti, esse sono tutte
+dichiarate nell'header file \texttt{unistd.h}.
-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}.
-
- \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},
+\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}.
- Le funzioni restituiscono zero in caso di successo e -1 per un errore, in
- caso di errore \texttt{errno} viene settato ai valori:
+ 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
+ \secref{sec:filedir_access_control}) ai quali si aggiungono i seguenti:
\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.
+ \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{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).
-
+\end{prototype}
-\subsection{I tempi dei file}
-\label{sec:filedir_file_times}
+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:
-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:
+\begin{prototype}{unistd.h}
+{int readlink(const char * path, char * buff, size\_t size)}
+ Legge il contenuto 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 per 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 è
+ 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}
+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
- \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} \\
+ \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{I tre tempi associati a ciascun file}
- \label{tab:filedir_file_times}
+ \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}).
+
+\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}.
-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).
+\subsection{Le funzioni \texttt{mkdir} e \texttt{rmdir}}
+\label{sec:filedir_dir_creat_rem}
-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.
+Per creare una nuova directory si può usare la seguente funzione, omonima
+dell'analogo comando di shell \texttt{mkdir}; per accedere ai tipi usati
+programma deve includere il file \texttt{sys/types.h}.
-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.
+\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.
+
+ 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
+ \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.
+ \item \texttt{EEXIST} Un file (o una directory) con quel nome esiste di già.
+ \item \texttt{EMLINK} La directory in cui si vuole creare la nuova directory
+ contiene troppi file. Sotto Linux questo normalmente non avviene perché il
+ filesystem standard consente la creazione di un numero di file maggiore di
+ quelli che possono essere contenuti nell'hard-disk, ma potendo avere a che
+ fare anche con filesystem di altri sistemi questo errore può presentarsi.
+ \item \texttt{ENOSPC} Non c'è abbastanza spazio sul file system per creare
+ la nuova directory.
+ \item \texttt{EROFS} La directory su cui si vuole inserire la nuova
+ directory è su un filesystem montato readonly.
+ \end{errlist}
+\end{prototype}
+
-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.
+\subsection{Accesso alle directory}
+\label{sec:filedir_dir_read}
-\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}
+Benché le directory siano oggetti del filesystem come tutti gli altri non ha
+ovviamente senso aprirle come fossero dei file di dati. Può però essere utile
+poterne leggere il contenuto ad esempio per fare la lista dei file che esse
+contengono o ricerche sui medesimi.
-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.
+Per accedere al contenuto delle directory si usano i cosiddetti
+\textit{directory streams} (chiamati così per l'analogia con i file stream);
+la funzione \texttt{opendir} apre uno di questi stream e la funzione
+\texttt{readdir} legge il contenuto della directory, i cui elementi sono le
+\textit{directory entries} (da distinguersi da quelle della cache di cui
+parlavamo in \secref{sec:fileintr_vfs}) in una opportuna struttura
+\texttt{struct dirent}.
-\subsection{La funzione \texttt{utime}}
-\label{sec:filedir_utime}
+\subsection{La directory di lavoro}
+\label{sec:filedir_work_dir}
-I tempi di ultimo accesso e modifica possono essere cambiati usando la
-funzione \func{utime}, il cui prototipo è:
+A ciascun processo è associato ad una directory nel filesystem che è chiamata
+directory corrente o directory di lavoro (\textit{current working directory})
+che è quella a cui si fa riferimento quando un filename è espresso in forma
+relativa (relativa appunto a questa directory).
-\begin{prototype}{utime.h}
-{int utime(const char * filename, struct utimbuf *times)}
+Quando un utente effettua il login questa directory viene settata alla
+cosiddetta \textit{home directory} del suo account, il comando \texttt{cd}
+della shell consente di cambiarla a piacere, spostandosi da una directory ad
+un'altra. Siccome la directory corrente resta la stessa quando viene creato
+un processo figlio, la directory corrente della shell diventa anche la
+directory corrente di qualunque comando da essa lanciato.
-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.
+Le funzioni qui descritte servono esaminare e cambiare la directory di lavoro
+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}
+\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
+ specificare un puntatore nullo come \textit{buffer}, nel qual caso la
+ stringa sarà allocata automaticamente per una dimensione pari a
+ \texttt{size} qualora questa sia diversa da zero, o della lunghezza esatta
+ del pathname altrimenti. In questo caso si deve ricordare di disallocare la
+ stringa una volta cessato il suo utilizzo.
+
+ La funzione restituisce il puntatore \texttt{buffer} se riesce,
+ \texttt{NULL} se fallisce, in quest'ultimo caso la variabile
+ \texttt{errno} è settata con i seguenti codici di errore:
+ \begin{errlist}
+ \item \texttt{EINVAL} L'argomento \texttt{size} è zero e \texttt{buffer} non
+ è nullo.
+ \item \texttt{ERANGE} L'argomento \texttt{size} è più piccolo della
+ lunghezza del pathname.
+ \item \texttt{EACCESS} Manca il permesso di lettura o di ricerca su uno dei
+ componenti del pathname (cioè su una delle directory superiori alla
+ corrente).
+ \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).
+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 bytes, vedi
+\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.
-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.
+Una seconda funzione simile è \texttt{char * get\_current\_dir\_name(void)}
+che è sostanzialmente equivalente ad una \texttt{getcwd(NULL, 0)}, con la sola
+differenza che essa ritorna il valore della variabile di ambiente
+\texttt{PWD}, che essendo costruita dalla shell può contenere anche dei
+riferimenti simbolici.
+
+Come già detto in unix anche le directory sono file, è possibile pertanto
+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{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 specificata dal pathname
+ contenuto nella stringa \texttt{pathname}.
+\end{prototype}
+
+\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
+ \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{prototype}