X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=filedir.tex;h=1f0edcd66b40e82a0c62684b45025bd8aeb4170a;hp=c071ecaac899423d1b984aa7eb60bcb347a8049e;hb=429f6e0da8fc282eb6611b6fe83fdf58ae8da611;hpb=daacafbdd3ae5d8fa4b68ecdcc2a5c97fd5128b7 diff --git a/filedir.tex b/filedir.tex index c071eca..1f0edcd 100644 --- a/filedir.tex +++ b/filedir.tex @@ -1,547 +1,619 @@ -\chapter{Files e directories} +\chapter{File e directory} \label{cha:files_and_dirs} In questo capitolo tratteremo in dettaglio le modalità con cui si gestiscono -files e directories, ed in particolare 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 del contenuto -dei file è lasciato ai capitoli successivi. +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. -\section{La gestione 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}). +\section{Il controllo di accesso ai file} +\label{sec:file_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:file_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 i permessi 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 (\acr{uid} e \acr{gid}). Questi valori +sono accessibili da programma tramite i campi \var{st\_uid} e \var{st\_gid} +della struttura \var{stat} (si veda \secref{sec:file_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, così come vengono presi dai comandi e dalle routine di sistema, +sono espressi da un numero 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 nei comandi di sistema con le lettere \cmd{w}, \cmd{r} e +\cmd{x}) ed applicabili rispettivamente al proprietario, al gruppo, a tutti +gli altri. I restanti tre bit (\acr{suid}, \acr{sgid}, e +\textsl{sticky}) sono usati per indicare alcune caratteristiche più complesse +su cui torneremo in seguito (vedi \secref{sec:file_suid_sgid} e +\secref{sec:file_sticky}). + +Anche i permessi, come tutte le altre informazioni generali, sono tenuti per +ciascun file nell'inode; in particolare essi sono contenuti in alcuni bit +del campo \var{st\_mode} della struttura letta da \func{stat} (di nuovo si veda +\secref{sec:file_stat} per i dettagli). + +In genere ci si riferisce a questo raggruppamento dei permessi usando le +lettere \cmd{u} (per \textit{user}), \cmd{g} (per \textit{group}) e \cmd{o} +(per \textit{other}), inoltre se si vuole indicare tutti i raggruppamenti +insieme si usa la lettera \cmd{a} (per \textit{all}). Si tenga ben presente +questa distinzione dato che in certi casi, mutuando la terminologia in uso nel +VMS, si parla dei permessi base come di permessi per \textit{owner}, +\textit{group} ed \textit{all}, le cui iniziali possono dar luogo a confusione. +Le costanti che permettono di accedere al valore numerico di questi bit nel +campo \var{st\_mode} sono riportate in \ntab. -\subsection{Le funzioni \texttt{link} e \texttt{unlink}} -\label{sec:fileintr_link} +\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} -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. +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). + +Avere 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. Avere 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 del contenuto del file dal +disco), non è necessario nessun tipo di permesso per il file stesso (infatti +esso non viene toccato, viene solo modificato il contenuto della directory, +rimuovendo la voce che ad esso fa rifermento). + +Per poter eseguire un file (che sia un programma compilato od uno script di +shell, od un altro tipo di file eseguibile riconosciuto dal kernel), occorre +avere il permesso di esecuzione, inoltre solo i file regolari possono essere +eseguiti. + +I permessi per un link simbolico sono ignorati, contano quelli del file a cui +fa riferimento; per questo in genere \cmd{ls} per un link simbolico riporta +tutti i permessi come concessi; utente e gruppo a cui esso appartiene vengono +ignorati quando il link viene risolto, vengono controllati solo quando viene +richiesta la rimozione del link e quest'ultimo è in una directory con lo +\textsl{sticky bit} settato (si veda \secref{sec:file_sticky}). + +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:proc_perms}; normalmente, a parte quanto vedremo in +\secref{sec:file_suid_sgid}, l'\textit{effective user id} e +l'\textit{effective group id} corrispondono a \acr{uid} e \acr{gid} +dell'utente che ha lanciato il processo, mentre i \textit{supplementary group + id} sono quelli dei gruppi cui l'utente appartiene. + +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 \acr{gid} del + file allora: + \begin{itemize} + \item se il bit dei permessi d'accesso del gruppo è settato, l'accesso è + consentito, + \item 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 bit \acr{suid} e \acr{sgid}} +\label{sec:file_suid_sgid} + +Come si è accennato (in \secref{sec:file_perm_overview}) nei dodici bit del +campo \var{st\_mode} usati per il controllo di accesso oltre ai bit dei +permessi veri e propri, ci sono altri tre bit che vengono usati per indicare +alcune proprietà speciali dei file. Due di questi sono i bit detti +\acr{suid} (o \textit{set-user-ID bit}) e \acr{sgid} (o +\textit{set-group-ID bit}) che sono identificati dalle constanti +\macro{S\_ISUID} e \macro{S\_ISGID}. + +Come spiegato in dettaglio in \secref{sec:proc_exec}, quando si lancia un +programma il comportamendo normale del kernel è quello di settare +l'\textit{effective user id} e l'\textit{effective group id} del nuovo +processo all'\acr{uid} e al \acr{gid} del processo corrente, che normalmente +corrispondono dell'utente con cui si è entrati nel sistema. + +Se però il file del programma\footnote{per motivi di sicurezza il kernel + ignora i bit \acr{suid} e \acr{sgid} per gli script eseguibili} (che +ovviamente deve essere eseguibile) ha il bit \acr{suid} settato, il kernel +assegnerà come \textit{effective user id} al nuovo processo l'uid del +proprietario del file al posto dell'uid del processo originario. Avere il bit +\acr{sgid} settato ha lo stesso effetto sull'\textit{effective group id} del +processo. + +I bit \textsl{suid} e \textsl{sgid} vengono usati 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, quest'ultimo ovviamente può essere scritto solo +dall'amministratore, ma non è necessario chiamare l'amministratore per +cambiare la propria password. Infatti il comando \cmd{passwd} appartiene a +root ma ha il bit suid settato per cui quando viene lanciato da un utente +normale parte con i privilegi di root. + +Chiaramente avere un processo che ha privilegi superiori a quelli che avrebbe +normalmente l'utente che lo ha lanciato comporta vari rischi, e questo tipo di +programmi devono essere scritti accuratamente per evitare che possano essere +usati per guadagnare privilegi non consentiti (torneremo sull'argomento in +\secref{sec:proc_perms}). + +La presenza dei bit \acr{suid} e \acr{sgid} su un file può essere +rilevata con il comando \cmd{ls -l}, in tal caso comparirà la lettera \cmd{s} +al posto della \cmd{x} in corrispondenza dei permessi di utente o gruppo. La +stessa lettera \cmd{s} può essere usata nel comando \cmd{chmod} per settare +questi bit. Infine questi bit possono essere controllati all'interno di +\var{st\_mode} con l'uso delle due costanti \macro{S\_ISUID} e +\macro{S\_IGID}, i cui valori sono riportati in +\tabref{tab:file_mode_flags}. + +Gli stessi bit vengono ad assumere in significato completamente diverso per le +directory, normalmente infatti Linux usa la convenzione di SVR4 per indicare +con questi bit l'uso della semantica BSD nella creazione di nuovi file (si +veda \secref{sec:file_ownership} per una spiegazione dettagliata al +proposito). + +Infine Linux utilizza il bit \acr{sgid} per una ulteriore estensione +mutuata da SVR4. Il caso in cui il file abbia il bit \acr{sgid} settato ma +non il corrispondente bit di esecuzione viene utilizzato per attivare per +quel file il \textit{mandatory locking} (argomento che affronteremo nei +dettagli in \secref{sec:xxx_mandatory_lock}). + + +\subsection{Il bit \textsl{sticky}} +\label{sec:file_sticky} + +L'ultimo dei bit rimanenti, identificato dalla costante \macro{S\_ISVTX}, è in +parte un rimasuglio delle origini dei sistemi unix. A quell'epoca infatti la +memoria virtuale e l'accesso ai files erano molto meno sofisticati e per +ottenere la massima velocità possibile per i programmi usati più comunemente +si poteva settare questo bit. + +L'effetto di questo bit era che il segmento di testo del programma (si veda +\secref{sec:proc_mem_layout} per i dettagli) veniva scritto nella swap la +prima volta che questo veniva lanciato, e vi permaneva fino al riavvio della +mecchina (da questo il nome di \textsl{sticky bit}); essendo la swap un file +continuo indicizzato direttamente in questo modo si poteva risparmiare in +tempo di caricamento rispetto alla ricerca del file su disco. Lo +\textsl{sticky bit} è indicato usando la lettera \cmd{t} al posto della +\cmd{x} nei permessi per gli altri. + +Ovviamente per evitare che gli utenti potessero intasare la swap solo +l'amministratore era in grado di settare questo bit, che venne chiamato anche +con il nome di \textit{saved text bit}, da cui deriva quello della costante. +Le attuali implementazioni di memoria virtuale e filesystem rendono +sostanzialmente inutile questo procedimento. + +Benché ormai non venga più utilizzato per i file, lo \textsl{sticky bit} ha +assunto un uso corrente per le directory\footnote{lo \textsl{sticky bit} per + le directory è una estensione non definita nello standard POSIX, Linux però + la supporta, così come BSD e SVR4}, in questo caso se il bit è settato un +file potrà essere rimosso dalla directory soltanto se l'utente ha il permesso +di scrittura ed inoltre è vera una delle seguenti condizioni: +\begin{itemize} +\item l'utente è proprietario del file +\item l'utente è proprietario della directory +\item l'utente è l'amministratore +\end{itemize} +un classico esempio di directory che ha questo bit settato è \file{/tmp}, i +permessi infatti di solito sono settati come: +\begin{verbatim} +$ ls -ld /tmp +drwxrwxrwt 6 root root 1024 Aug 10 01:03 /tmp +\end{verbatim}%$ +in questo modo chiunque può leggere, scrivere ed eseguire i file temporanei +ivi memorizzati, sia crearne di nuovi, ma solo l'utente che ha creato un file +nella directory potrà cancellarlo o rinominarlo, così si può evitare che un +utente possa, più o meno consapevolemnte, cancellare i file degli altri. + + +\subsection{La titolarità di nuovi file e directory} +\label{sec:file_ownership} + +Vedremo in \secref{sec:file_base_func} come creare nuovi file, ma se è +possibile specificare in sede di creazione quali permessi applicare ad un +file, non si può indicare a quale utente e gruppo esso deve appartenere. Lo +stesso problema di presenta per la creazione di nuove directory (procedimento +descritto in \secref{sec:file_dir_creat_rem}). + +Lo standard POSIX prescrive che l'uid del nuovo file corrisponda +all'\textit{effective user id} del processo che lo crea; per il \acr{gid} +invece prevede due diverse possibilità: +\begin{itemize} +\item il \acr{gid} del file corrisponde all'\textit{effective group id} del + processo. +\item il \acr{gid} del file corrisponde al gid della directory in cui esso è + creato. +\end{itemize} +in genere BSD usa sempre la seconda possibilità, che viene per questo chiamata +semantica BSD. Linux invece segue quella che viene chiamata semantica SVR4; di +norma cioè il nuovo file viene creato, seguendo la prima opzione, con il +\acr{gid} del processo, se però la directory in cui viene creato il file ha il +bit \acr{sgid} settato allora viene usata la seconda opzione.. + +Usare la semantica BSD ha il vantaggio che il \acr{gid} viene sempre +automaticamente propagato, restando coerente a quello della directory di +partenza, in tutte le sottodirectory. La semantica SVR4 offre una maggiore +possibilità di scelta, ma per ottenere lo stesso risultato necessita che per +le nuove directory venga anche propagato anche il bit \acr{sgid}. Questo è +comunque il comportamento di default di \func{mkdir}, ed é in questo modo ad +esempio che Debian assicura che le sottodirectory create nelle home di un +utente restino sempre con il \acr{gid} del gruppo primario dello stesso. -Come si è appena detto l'accesso al contenuto di un file su disco avviene -attraverso il suo inode, e il nome che si trova in una directory è solo una -etichetta associata ad un puntatore a detto inode. Questo significa che la -realizzazione di un link è immediata in quanto uno stesso file può avere tanti -nomi diversi allo stesso tempo, dati da altrettante diverse associazioni allo -stesso inode; si noti poi che nessuno di questi nomi viene ad assumere una -particolare preferenza rispetto agli altri. -Per aggiungere un nome ad un inode si utilizza la funzione \texttt{link}; si -suole chiamare questo tipo di associazione un collegamento diretto (o -\textit{hard link}). Il prototipo della funzione e le sue caratteristiche -principali, come risultano dalla man page, sono le seguenti: +\subsection{La funzione \texttt{access}} +\label{sec:file_access} + +Come detto in \secref{sec:file_access_control} il controllo di accesso ad +un file viene fatto usando \textit{effective user id} e \textit{effective + group id} del processo, ma ci sono casi in cui si può voler effettuare il +controllo usando il \textit{real user id} e il \textit{real group id} (cioè +l'uid dell'utente che ha lanciato il programma, che, come accennato in +\secref{sec:file_suid_sgid} e spiegato in \secref{sec:proc_perms} non è +detto sia uguale all'\textit{effective user id}). Per far questo si può usare +la funzione \func{access}, il cui prototipo è: + \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}. +{int access(const char *pathname, int mode)} + + La funzione verifica i permessi di accesso, indicati da \var{mode}, per il + file indicato da \var{pathname}. - 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: - \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{EFAULT} una delle stringhe passate come parametri è fuori - dello spazio di indirizzi del processo. - \item \texttt{EACCESS} errore di accesso (mancano i permessi per scrivere o - per attraversare le directories), vedi \secref{sec:filedir_access_control} - per i dettagli. - \item \texttt{ENAMETOOLONG} una dei due pathname è troppo lungo. - \item \texttt{ENOENT} un componente di \texttt{oldpath} o \texttt{newpath} - non esiste o è un link simbolico spezzato. - \item \texttt{ENOTDIR} un componente di \texttt{oldpath} o \texttt{newpath} - non è una directory. - \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a - completare l'operazione. - \item \texttt{EROFS} la directory su cui si vuole inserire il nuovo link è - su un filesystem montato readonly. - \item \texttt{EEXIST} un file (o una directory) con quel nome esiste di - già. - \item \texttt{EMLINK} ci sono troppi link al file \texttt{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} + La funzione ritorna 0 se l'accesso è consentito, -1 altrimenti; in + quest'ultimo caso la variabile \texttt{errno} viene settata secondo i codici + di errore: \macro{EACCES}, \macro{EROFS}, \macro{EFAULT}, \macro{EINVAL}, + \macro{ENAMETOOLONG}, \macro{ENOENT}, \macro{ENOTDIR}, \macro{ELOOP}, + \macro{EIO}. \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). +I valori possibili per il parametro \var{mode} sono esprimibili come +combinazione delle costanti numeriche riportate in \ntab\ (attraverso un OR +binario). I primi tre valori implicano anche la verifica dell'esistenza del +file, se si vuole verificare solo quest'ultimaa si può usare \macro{F\_OK}, o +anche direttamente \func{stat}. In caso \var{pathname} si riferisca ad un link +simbolico il controllo è fatto sul file a cui esso fa riferimento. -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 funzione controlla solo i bit dei permessi di accesso, si ricordi che il +fatto che una directory abbia permesso di scrittura non significa che ci si +possa scrivere come in un file, e il fatto che un file abbia permesso di +esecuzione non comporta che contenga un programma eseguibile. La funzione +ritorna zero solo se tutte i permessi controllati sono disponibili, in caso +contrario (o di errore) ritorna -1. -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{table}[htb] + \centering + \begin{tabular}{|c|l|} + \hline + \var{mode} & Significato \\ + \hline + \hline + \macro{R\_OK} & verifica il permesso di lettura \\ + \macro{W\_OK} & verifica il permesso di scritture \\ + \macro{X\_OK} & verifica il permesso di esecuzione \\ + \macro{F\_OK} & verifica l'esistenza del file \\ + \hline + \end{tabular} + \caption{Valori possibile per il parametro \var{mode} della funzione + \func{access}} + \label{tab:file_access_mode_val} +\end{table} -\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. +Un esempio tipico per l'uso di questa funzione è quello di un processo che sta +eseguendo un programma coi privilegi di un altro utente (attraverso l'uso del +suid bit) che vuole controllare se l'utente originale ha i permessi per +accedere ad un certo file. + + +\subsection{Le funzioni \texttt{chmod} e \texttt{fchmod}} +\label{sec:file_chmod} + +Per cambiare i permessi di un file il sistema mette ad disposizione due +funzioni, che operano rispettivamente su un filename e su un file descriptor, +i cui prototipi sono: + +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/stat.h} - 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: + \funcdecl{int chmod(const char *path, mode\_t mode)} Cambia i permessi del + file indicato da \var{path} al valore indicato da \var{mode}. + + \funcdecl{int fchmod(int fd, mode\_t mode)} Analoga alla precedente, ma usa + il file descriptor \var{fd} per indicare il file. + + Le funzioni restituiscono zero in caso di successo e -1 per un errore, in + caso di errore \texttt{errno} può assumere i valori: \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{EISDIR} \texttt{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{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 \macro{EPERM} L'\textit{effective user id} non corrisponde a quello + del proprietario del file o non è zero. \end{errlist} -\end{prototype} + ed inoltre \macro{EROFS} e \macro{EIO}; \func{chmod} restituisce anche + \macro{EFAULT}, \macro{ENAMETOOLONG}, \macro{ENOENT}, \macro{ENOMEM}, + \macro{ENOTDIR}, \macro{EACCES}, \macro{ELOOP}; \func{fchmod} anche + \macro{EBADF}. +\end{functions} -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). +I valori possibili per \var{mode} sono indicati in \ntab. I valori possono +esser combinati con l'OR binario delle relative macro, o specificati +direttamente, come per l'analogo comando di shell, con il valore ottale. Ad +esempio i permessi standard assegnati ai nuovi file (lettura e scrittura per +il proprietario, sola lettura per il gruppo e gli altri) sono corrispondenti +al valore ottale $0644$, un programma invece avrebbe anche il bit di +esecuzione attivo, con un valore di $0755$, se si volesse attivare il bit suid +il valore da fornire sarebbe $4755$. -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. +\begin{table}[!htb] + \centering + \begin{tabular}[c]{|c|c|l|} + \hline + \var{mode} & Valore & Significato \\ -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. + \hline + \hline + \macro{S\_ISUID} & 04000 & set user ID \\ + \macro{S\_ISGID} & 02000 & set group ID \\ + \macro{S\_ISVTX} & 01000 & sticky bit \\ + \hline + \macro{S\_IRWXU} & 00700 & l'utente ha tutti i permessi \\ + \macro{S\_IRUSR} & 00400 & l'utente ha il permesso di lettura \\ + \macro{S\_IWUSR} & 00200 & l'utente ha il permesso di scrittura \\ + \macro{S\_IXUSR} & 00100 & l'utente ha il permesso di esecuzione \\ + \hline + \macro{S\_IRWXG} & 00070 & il gruppo ha tutti i permessi \\ + \macro{S\_IRGRP} & 00040 & il gruppo ha il permesso di lettura \\ + \macro{S\_IWGRP} & 00020 & il gruppo ha il permesso di scrittura \\ + \macro{S\_IXGRP} & 00010 & il gruppo ha il permesso di esecuzione \\ + \hline + \macro{S\_IRWXO} & 00007 & gli altri hanno tutti i permessi \\ + \macro{S\_IROTH} & 00004 & gli altri hanno il permesso di lettura \\ + \macro{S\_IWOTH} & 00002 & gli altri hanno il permesso di scrittura \\ + \macro{S\_IXOTH} & 00001 & gli altri hanno il permesso di esecuzione \\ + \hline + \end{tabular} + \caption{I valori delle costanti usate per indicare i permessi dei file.} + \label{tab:file_permission_const} +\end{table} -\subsection{Le funzioni \texttt{remove} e \texttt{rename}} -\label{sec:fileintr_remove} +Il cambiamento dei permessi di un file attraverso queste funzioni ha comunque +alcune limitazioni, provviste per motivi di sicurezza. Questo significa che +anche se si è proprietari del file non tutte le operazioni sono permesse, in +particolare: +\begin{itemize} +\item siccome solo l'amministratore può settare lo \textit{sticky bit} se se + l'\textit{effective user id} del processo non è zero esso viene + automaticamente cancellato (senza notifica di errore) qualora sia stato + indicato in \var{mode}. +\item per via della semantica SVR4 nella creazione dei nuovi file, si può + avere il caso in cui il file creato da un processo è assegnato a un gruppo + per il quale il processo non ha privilegi. Per evitare che si possa + assegnare il bit \acr{sgid} ad un file appartenente a un gruppo per cui + non si hanno diritti, questo viene automaticamente cancellato (senza + notifica di errore) da \var{mode} qualora il gruppo del file non corrisponda + a quelli associati al processo (la cosa non avviene quando + l'\textit{effective user id} del processo è zero). +\end{itemize} + +Per alcuni filesystem\footnote{il filesystem \textsl{ext2} supporta questa + caratteristica, che è mutuata da BSD.} è inoltre prevista una ulteriore +misura di sicurezza, volta ad scongiurare l'abuso dei bit \acr{suid} e +\acr{sgid}; essa consiste nel cancellare automaticamente questi bit qualora un +processo che non appartenga all'amministratore scriva su un file. In questo +modo anche se un utente malizioso scopre un file \acr{suid} su cui può +scrivere, un eventuale modifica comporterà la perdita di ogni ulteriore +privilegio. -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{La funzione \texttt{umask}} +\label{sec:file_umask} -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 che dai valori indicati in sede di creazione, i permessi assegnati ai +nuovi file sono controllati anche da una maschera di bit settata con la +funzione \func{umask}, il cui prototipo è: -\begin{prototype}{stdio.h} -{int rename(const char *oldpath, const char *newpath)} - Rinomina un file, spostandolo fra directory diverse quando richiesto. +\begin{prototype}{stat.h} +{mode\_t umask(mode\_t mask)} - 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} + Setta la maschera dei permessi dei bit al valore specificato da \var{mask} + (di cui vengono presi solo i 9 bit meno significativi). + + La funzione ritorna il precedente valore della maschera. È una delle poche + funzioni che non restituisce codici di errore. \end{prototype} -\subsection{I link simbolici} -\label{sec:fileintr_symlink} +Questa maschera è una caratteristica di ogni processo e viene utilizzata per +impedire che alcuni permessi possano essere assegnati ai nuovi file in sede di +creazione, i bit indicati nella maschera vengono infatti esclusi quando un +nuovo file viene creato. + +In genere questa maschera serve per impostare un default che escluda alcuni +permessi (usualmente quello di scrittura per il gruppo e gli altri, +corrispondente ad un valore di $022$). Essa è utile perché le routine +dell'interfaccia ANSI C degli stream non prevedono l'esistenza dei permessi, e +pertanto tutti i nuovi file vengono sempre creati con un default di $666$ +(cioè permessi di lettura e scrittura per tutti, si veda +\tabref{tab:file_permission_const} per un confronto); in questo modo è +possibile cancellare automaticamente i permessi non voluti, senza doverlo fare +esplicitamente. + +In genere il valore di \func{umask} viene stabilito una volta per tutte al +login a $022$, e di norma gli utenti non hanno motivi per modificarlo. Se però +si vuole che un processo possa creare un file che chiunque possa leggere +allora occorrerà cambiare il valore di \func{umask}. -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{Le funzioni \texttt{chown}, \texttt{fchown} e \texttt{lchown}} +\label{sec:file_chown} -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. +Come per i permessi, il sistema fornisce anche delle funzioni che permettano +di cambiare utente e gruppo cui il file appartiene; le funzioni in questione +sono tre e i loro prototipi sono i seguenti: -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. +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/stat.h} + + \funcdecl{int chown(const char *path, uid\_t owner, gid\_t group)} + \funcdecl{int fchown(int fd, uid\_t owner, gid\_t group)} + \funcdecl{int lchown(const char *path, uid\_t owner, gid\_t group)} -Le funzioni per operare sui link simbolici sono le seguenti, esse sono tutte -dichiarate nell'header file \texttt{unistd.h}. + Le funzioni cambiano utente e gruppo di appartenenza di un file ai valori + specificati dalle variabili \var{owner} e \var{group}. -\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: + 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 \macro{EPERM} L'\textit{effective user id} non corrisponde a quello + del proprietario del file o non è zero, o utente e gruppo non sono validi \end{errlist} -\end{prototype} + Oltre a questi entrambe restituiscono gli errori \macro{EROFS} e + \macro{EIO}; \func{chown} restituisce anche \macro{EFAULT}, + \macro{ENAMETOOLONG}, \macro{ENOENT}, \macro{ENOMEM}, \macro{ENOTDIR}, + \macro{EACCES}, \macro{ELOOP}; \func{fchown} anche \macro{EBADF}. +\end{functions} -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: +In Linux soltanto l'amministratore può cambiare il proprietario di un file, +seguendo la semantica di BSD che non consente agli utenti di assegnare i loro +file ad altri (per evitare eventuali aggiramenti delle quote). +L'amministratore può cambiare il gruppo di un file, il proprietario può +cambiare il gruppo dei file che gli appartengono solo se il nuovo gruppo è il +suo gruppo primario o uno dei gruppi a cui appartiene. + +La funzione \func{chown} segue i link simbolici, per operare direttamente su +in link simbolico si deve usare la funzione \func{lchown}\footnote{fino alla + versione 2.1.81 in Linux \func{chown} non seguiva i link simbolici, da + allora questo comportamento è stato assegnato alla funzione \func{lchown}, + introdotta per l'occazione, ed è stata creata una nuova system call per + \func{chown} che seguisse i link simbolici}. La funzione \func{fchown} opera +su un file aperto, essa è mututata da BSD, ma non è nello standard POSIX. +Un'altra estensione rispetto allo standard POSIX è che specificando -1 come +valore per \var{owner} e \var{group} i valori restano immutati. + +Quando queste funzioni sono chiamate con successo da un processo senza i +privilegi di root entrambi i bit \acr{suid} e \acr{sgid} vengono +cancellati. Questo non avviene per il bit \acr{sgid} nel caso in cui esso +sia usato (in assenza del corrispondente permesso di esecuzione) per indicare +che per il file è attivo il \textit{mandatory locking}. -\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} +%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}). -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}). - -\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}. - - -\subsection{Le funzioni \texttt{mkdir} e \texttt{rmdir}} -\label{sec:filedir_dir_creat_rem} - -Per creare una nuova directory si può usare la seguente funzione, omonima -dell'analogo comando di shell \texttt{mkdir}; per accedere ai tipi usati -programma deve includere il file \texttt{sys/types.h}. - -\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} - - -\subsection{Accesso alle directory} -\label{sec:filedir_dir_read} - -Benché le directory siano oggetti del filesystem come tutti gli altri non ha -ovviamente senso aprirle come fossero dei file di dati. Può però essere utile -poterne leggere il contenuto ad esempio per fare la lista dei file che esse -contengono o ricerche sui medesimi. - -Per accedere al contenuto delle directory si usano i cosiddetti -\textit{directory streams} (chiamati così per l'analogia con i file stream); -la funzione \texttt{opendir} apre uno di questi stream e la funzione -\texttt{readdir} legge il contenuto della directory, i cui elementi sono le -\textit{directory entries} (da distinguersi da quelle della cache di cui -parlavamo in \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. - -\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} - -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. - -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} \section{La manipolazione delle caratteristiche dei files} -\label{sec:filedir_infos} +\label{sec:file_infos} + +Come spiegato in \secref{sec:file_filesystem} tutte le informazioni +generali relative alle caratteristiche di ciascun file, a partire dalle +informazioni relative al controllo di accesso, sono mantenute nell'inode. -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}. +Vedremo in questa sezione come sia possibile leggere tutte queste informazioni +usando la funzione \texttt{stat}, che permette l'accesso a tutti i dati +memorizzati nell'inode; esamineremo poi le varie funzioni usate per manipolare +tutte queste informazioni (eccetto quelle che riguardano la gestione del +controllo di accesso, già trattate in in \secref{sec:file_access_control}). \subsection{Le funzioni \texttt{stat}, \texttt{fstat} e \texttt{lstat}} -\label{sec:filedir_stat} +\label{sec:file_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: +delle funzioni \func{stat}; questa è la funzione che il comando \cmd{ls} usa +per poter ottenere e mostrare tutti i dati dei files. I prototipi di queste +funzioni sono i seguenti: \begin{functions} \headdecl{sys/types.h} \headdecl{sys/stat.h} @@ -560,17 +632,9 @@ i seguenti: 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} + caso di errore \texttt{errno} può assumere uno dei valori: \macro{EBADF}, + \macro{ENOENT}, \macro{ENOTDIR}, \macro{ELOOP}, \macro{EFAULT}, + \macro{EACCESS}, \macro{ENOMEM}, \macro{ENAMETOOLONG}. \end{functions} La struttura \texttt{stat} è definita nell'header \texttt{sys/stat.h} e in @@ -604,7 +668,7 @@ struct stat { \normalsize \caption{La struttura \texttt{stat} per la lettura delle informazioni dei file} - \label{fig:filedir_stat_struct} + \label{fig:file_stat_struct} \end{figure} Si noti come i vari membri della struttura siano specificati come tipi nativi @@ -613,16 +677,18 @@ del sistema (di quelli definiti in \tabref{tab:xxx_sys_types}, e dichiarati in \subsection{I tipi di file} -\label{sec:filedir_file_types} +\label{sec:file_types} -Come riportato in \tabref{tab:fileintr_file_types} in Linux oltre ai file e +Come riportato in \tabref{tab:file_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}. +il tipo di file è ritornato dalla \texttt{stat} nel campo \texttt{st\_mode} +(che è quello che contiene anche le informazioni relative ai permessi). -Dato che il valore numerico può variare a seconda delle implementazioni lo +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: +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 @@ -631,7 +697,7 @@ simbolici e socket definite da BDS, l'elenco Macro & Tipo del file \\ \hline \hline - \macro{S\_ISREG(m)} & file normale \\ + \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\\ @@ -641,7 +707,7 @@ simbolici e socket definite da BDS, l'elenco \hline \end{tabular} \caption{Macro per i tipi di file (definite in \texttt{sys/stat.h})} - \label{tab:filedir_file_type_macro} + \label{tab:file_type_macro} \end{table} Oltre a queste macro è possibile usare direttamente il valore di @@ -656,35 +722,38 @@ per questo sempre in \texttt{sys/stat.h} sono definiti i flag riportati in 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 \\ + \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{Flag per il campo \var{st\_mode} (definite in - \texttt{sys/stat.h})} - \label{tab:filedir_file_mode_flags} + \caption{Costanti per l'identificazione dei vari bit che compongono il campo + \var{st\_mode} (definite in \texttt{sys/stat.h})} + \label{tab:file_mode_flags} \end{table} Il primo valore definisce la maschera dei bit usati nei quali viene @@ -693,15 +762,16 @@ 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) ) +#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} +\label{sec:file_file_size} -Il membro \var{st\_size} contiene la dimensione del file in bytes (se il file +Il membro \var{st\_size} contiene la dimensione del file in byte (se il file è un file normale, nel caso di un link simbolico al dimensione è quella del pathname che contiene). @@ -715,7 +785,7 @@ Si tenga conto che lunghezza del file riportata in \var{st\_size} non 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 +una \func{seek} (vedi \secref{sec:file_lseek}) oltre la sua conclusione corrente. In tal caso si avranno differenti risultati a seconda del modi in cui si @@ -740,21 +810,24 @@ le due funzioni: \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}, + 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: + caso di errore \texttt{errno} viene settato opportunamente; per + \func{ftruncate} si hanno i valori: + \begin{errlist} + \item \macro{EBADF} \var{fd} non è un file descriptor. + \item \texttt{EINVAL} \var{fd} è un riferimento ad un socket, non a un file + o non è aperto in scrittura. + \end{errlist} + per \func{truncate} si hanno: \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{EACCES} il file non ha permesso di scrittura o non si ha il + permesso di esecuzione una delle directory del pathname. + \item \texttt{ETXTBSY} Il file è un programma in esecuzione. \end{errlist} + ed anche \macro{ENOTDIR}, \macro{ENAMETOOLONG}, \macro{ENOENT}, + \macro{EROFS}, \macro{EIO}, \macro{EFAULT}, \macro{ELOOP}. \end{functions} Se il file è più lungo della lunghezza specificata i dati in eccesso saranno @@ -763,13 +836,14 @@ dipende dall'implementazione: il file pu 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} +\label{sec:file_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 +struttura in \figref{fig:file_stat_struct}. Il significato di detti tempi e dei relativi campi è riportato nello schema in \ntab: \begin{table}[htb] @@ -786,7 +860,7 @@ dei relativi campi \hline \end{tabular} \caption{I tre tempi associati a ciascun file} - \label{tab:filedir_file_times} + \label{tab:file_file_times} \end{table} Il primo punto da tenere presente è la differenza fra il cosiddetto tempo di @@ -885,16 +959,16 @@ cambiarne i permessi ha effetti solo sui tempi del file. \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} + \label{tab:file_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 +creazione del file, usato da molti altri sistemi operativi, che in unix non esiste. \subsection{La funzione \texttt{utime}} -\label{sec:filedir_utime} +\label{sec:file_utime} I tempi di ultimo accesso e modifica possono essere cambiati usando la funzione \func{utime}, il cui prototipo è: @@ -938,82 +1012,484 @@ direttamente sul disco senza passare attraverso il filesystem, ma ovviamente molto più complicato da realizzare. -\section{Il controllo di accesso ai file} -\label{sec:filedir_access_control} - -In unix è implementata da qualunque filesystem standard una forma elementare -(ma adatta alla maggior parte delle esigenze) di controllo di accesso ai -files. Torneremo sull'argomento in dettaglio più avanti (vedi -\secref{sec:filedir_access_control}), qui ci limitiamo ad una introduzione dei -concetti essenziali. - -Si tenga conto poi che quanto diremo è vero solo per filesystem di tipo Unix, -e non è detto che sia applicabile (ed infatti non è vero per il filesystem di -Windows) a un filesystem qualunque. Esistono inoltre estensioni che permettono -di implementare le ACL (\textit{Access Control List}) che sono un meccanismo -di controllo di accesso molto più sofisticato. - -Ad ogni file Unix associa sempre l'utente che ne è proprietario (il cosiddetto -\textit{owner}) e il gruppo di appartenenza, secondo il meccanismo degli uid e -gid 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. - -I permessi sono espressi da un insieme di 12 bit: di questi i nove meno -significativi sono usati a gruppi di tre per indicare i permessi base di -lettura, scrittura ed esecuzione (indicati rispettivamente con le lettere -\textit{w}, \textit{r} \textit{x}) applicabili rispettivamente al -proprietario, al gruppo, a tutti (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 \secref{sec:filedir_suid_sgid} e \secref{sec:filedir_sticky}). - -Tutte queste informazioni sono tenute per ciascun file nell'inode. Quando un -processo cerca l'accesso al file esso controlla i propri uid e gid -confrontandoli con quelli del file e se l'operazione richiesta è compatibile -con i permessi associati al file essa viene eseguita, altrimenti viene -bloccata ed è restituito un errore di \texttt{EPERM}. Questo procedimento non -viene eseguito per l'amministratore di sistema (il cui uid è zero) il quale ha -pertanto accesso senza restrizione a qualunque file del sistema. - -% In realtà il procedimento è più complesso di quanto descritto in maniera -% elementare qui; inoltre ad un processo sono associati diversi identificatori, -% torneremo su questo in maggiori dettagli in seguito in \secref{sec:proc_perms}. - -\subsection{I flag \texttt{suid} e \texttt{sgid}} -\label{sec:filedir_suid_sgid} +\section{La manipolazione di file e directory} +Come già accennato in \secref{sec:file_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:file_link} +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. -\subsection{La titolarità di nuovi files e directory} -\label{sec:filedir_ownership} +Come spiegato in \secref{sec:file_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. -\subsection{La funzione \texttt{access}} -\label{sec:filedir_access} +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} -\subsection{La funzione \texttt{umask}} -\label{sec:filedir_umask} +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:file_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). -\subsection{Le funzioni \texttt{chmod} e \texttt{fchmod}} -\label{sec:filedir_chmod} +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:file_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}. -\subsection{Il flag \texttt{sticky}} -\label{sec:filedir_sticky} +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: -\subsection{Le funzioni \texttt{chown}, \texttt{fchown} e \texttt{lchown}} -\label{sec:filedir_chown} +\begin{prototype}{unistd.h}{int unlink(const char * pathname)} + Cancella il nome specificato dal pathname nella relativa directory e + decrementa il numero di riferimenti nel relativo inode. Nel caso di link + simbolico cancella il link simbolico; nel caso di socket, fifo o file di + dispositivo rimuove il nome, ma come per i file i processi che hanno aperto + uno di questi oggetti possono continuare ad utilizzarlo. + + La funzione restituisce zero in caso di successo e -1 per un errore, nel + qual caso il file non viene toccato. La variabile \texttt{errno} viene + settata secondo i seguenti codici di errore: + \begin{errlist} + \item \texttt{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 + consentita 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} +Per cancellare una voce in una directory è necessario avere il permesso di +scrittura su di essa (dato che si va a rimuovere una voce dal suo contenuto) e +il diritto di esecuzione sulla directory che la contiene (torneremo in +dettaglio sui permessi e gli attributi fra poco), se inoltre lo +\textit{sticky} bit è settato occorrerà anche essere proprietari del file o +proprietari della directory (o root, per cui nessuna delle restrizioni è +applicata). +Una delle caratteristiche di queste funzioni è che la creazione/rimozione +della nome dalla directory e l'incremento/decremento del numero di riferimenti +nell'inode deve essere una operazione atomica (cioè non interrompibile da +altri) processi, per questo entrambe queste funzioni sono realizzate tramite +una singola system call. +Si ricordi infine che il file non viene eliminato dal disco fintanto che tutti +i riferimenti ad esso sono stati cancellati, solo quando il \textit{link + count} mantenuto nell'inode diventa zero lo spazio occupato viene rimosso. A +questo però si aggiunge una altra condizione, e cioè che non ci siano processi +che abbiano detto file aperto. Come accennato questa proprietà viene spesso +usata per essere sicuri di non lasciare file temporanei su disco in caso di +crash dei programmi; la tecnica è quella di aprire il file e chiamare +\texttt{unlink} subito dopo. + +\subsection{Le funzioni \texttt{remove} e \texttt{rename}} +\label{sec:file_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 +funzione \texttt{rmdir} (vedi \secref{sec:file_dir_creat_rem}), oppure la +funzione \texttt{remove}. Questa è la funzione prevista dallo standard ANSI C +per cancellare un file o una directory (e funziona anche per i sistemi che non +supportano i link diretti), che per i file è identica alla \texttt{unlink} e +per le directory è identica alla \texttt{rmdir}: + +\begin{prototype}{stdio.h}{int remove(const char *pathname)} + Cancella un nome dal filesystem. Usa \texttt{unlink} per i file e + \texttt{rmdir} per le directory. + + La funzione restituisce zero in caso di successo e -1 per un errore, nel + qual caso il file non viene toccato. Per i codici di errori vedi quanto + riportato nella descrizione di \texttt{unlink} e \texttt{rmdir}. +\end{prototype} + +Per cambiare nome ad un file si usa invece la funzione \texttt{rename}, il +vantaggio nell'uso di questa funzione al posto della chiamata successiva di +\texttt{unlink} e \texttt{link} è che l'operazione è eseguita atomicamente, in +questo modo non c'è la possibilità che un processo che cerchi di accedere al +nuovo nome dopo che il vecchio è stato cambiato lo trovi mancante. + +\begin{prototype}{stdio.h} +{int rename(const char *oldpath, const char *newpath)} + Rinomina un file, spostandolo fra directory diverse quando richiesto. + + La funzione restituisce zero in caso di successo e -1 per un errore, nel + qual caso il file non viene toccato. La variabile \texttt{errno} viene + settata secondo i seguenti codici di errore: + \begin{errlist} + \item \texttt{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{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{ENOSPC} Il device di destinazione non ha più spazio per la + nuova voce. + \end{errlist} +\end{prototype} + +\subsection{I link simbolici} +\label{sec:file_symlink} + +Siccome la funzione \texttt{link} crea riferimenti agli inodes, essa può +funzionare soltanto per file che risiedono sullo stesso filesystem, dato che +in questo caso è garantita l'unicità dell'inode, e solo per un filesystem di +tipo unix. Inoltre in Linux non è consentito eseguire un link diretto ad una +directory. + +Per ovviare a queste limitazioni i sistemi unix supportano un'altra forma di +link (i cosiddetti \textit{soft link} o \textit{symbolic link}), che sono, +come avviene in altri sistemi operativi, dei file che contengono il +semplicemente il riferimento ad un altro file (o directory). In questo modo è +possibile effettuare link anche attraverso filesystem diversi e a directory, e +pure a file che non esistono ancora. + +Il sistema funziona in quanto i link simbolici sono contrassegnati come tali +al kernel (analogamente a quanto avviene per le directory) per cui la chiamata +ad una \texttt{open} o una \texttt{stat} su un link simbolico comporta la +lettura del contenuto del medesimo e l'applicazione della funzione al file +specificato da quest'ultimo. Invece altre funzioni come quelle per cancellare +o rinominare i file operano direttamente sul link simbolico (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}. + +\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 file (trattati in dettaglio in + \secref{sec:file_access_control}) ai quali si aggiungono i seguenti: + \begin{errlist} + \item \texttt{EEXIST} Un file (o una directory) con quel nome esiste di + già. + \item \texttt{EROFS} La directory su cui si vuole inserire il nuovo link è + su un filesystem montato readonly. + \item \texttt{ENOSPC} La directory o il filesystem in cui si vuole creare il + link è piena e non c'è ulteriore spazio disponibile. + \item \texttt{ELOOP} Ci sono troppi link simbolici nella risoluzione di + \texttt{oldname} o di \texttt{newname}. + \end{errlist} +\end{prototype} + +Dato che la funzione \texttt{open} segue i link simbolici, è necessaria usare +un'altra funzione quando si vuole leggere il contenuto di un link simbolico, +questa funzione è la: + +\begin{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. + \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:file_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 effettuata 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:file_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 effettuano lo scan di +una directory senza tener conto dei link simbolici, ad esempio se lanciassimo +un comando del tipo \cmd{grep -r linux *}, il loop nella directory porterebbe +il comando ad esaminare \file{/boot}, \file/{boot/boot}, \file/{boot/boot/boot} +e così via, fino a generare un errore (che poi è \macro{ELOOP}) quando viene +superato il numero massimo di link simbolici consentiti (uno dei limiti del +sistema, posto proprio per poter uscire da questo tipo di situazione). + +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{Le funzioni \texttt{mkdir} e \texttt{rmdir}} +\label{sec:file_dir_creat_rem} + +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}. + +\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 + \var{dirname}, assegnandole i permessi indicati da \var{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 file (trattati in dettaglio in + \secref{sec:file_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} + + +\subsection{Accesso alle directory} +\label{sec:file_dir_read} + +Benché le directory siano oggetti del filesystem come tutti gli altri non ha +ovviamente senso aprirle come fossero dei file di dati. Può però essere utile +poterne leggere il contenuto ad esempio per fare la lista dei file che esse +contengono o ricerche sui medesimi. + +Per accedere al contenuto delle directory si usano i cosiddetti +\textit{directory streams} (chiamati così per l'analogia con i file stream); +la funzione \texttt{opendir} apre uno di questi stream e la funzione +\texttt{readdir} legge il contenuto della directory, i cui elementi sono le +\textit{directory entries} (da distinguersi da quelle della cache di cui +parlavamo in \secref{sec:file_vfs}) in una opportuna struttura +\texttt{struct dirent}. + +(NdA Il resto va scritto!!! É noioso e lo farò più avanti). + + + +\subsection{La directory di lavoro} +\label{sec:file_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. + +\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} + +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. + +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 file (trattati in dettaglio in + \secref{sec:file_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} -%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}).