From: Simone Piccardi Date: Mon, 30 Dec 2002 22:43:30 +0000 (+0000) Subject: Completate le funzioni per la lettura e la scansione delle directory X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=96256b851638bcd0bae29eafa53a22b01815490d;hp=1a416451168660c50fefa8802e5d531e331c8063 Completate le funzioni per la lettura e la scansione delle directory --- diff --git a/filedir.tex b/filedir.tex index 61e39aa..8b522d6 100644 --- a/filedir.tex +++ b/filedir.tex @@ -741,15 +741,15 @@ successiva. I dati vengono memorizzati in una struttura \struct{dirent} (la cui definizione\footnote{la definizione è quella usata a Linux, che si trova nel file \file{/usr/include/bits/dirent.h}, essa non contempla la presenza del campo \var{d\_namlen} che indica la lunghezza del nome del file (ed - infatti la macro \macro{\_DIRENT\_HAVE\_D\_NAMLEN} non è definita.} è + infatti la macro \macro{\_DIRENT\_HAVE\_D\_NAMLEN} non è definita).} è riportata in \figref{fig:file_dirent_struct}). La funzione restituisce il puntatore alla struttura; si tenga presente però che quest'ultima è allocata -staticamente, per cui viene sovrascritta tutte le volte che si ripete una -lettura sullo stesso stream. +staticamente, per cui viene sovrascritta tutte le volte che si ripete la +lettura di una voce sullo stesso stream. -Di questa funzione esiste anche una versione rientrante, \func{readdir\_r} che -non usa una struttura allocata staticamente, e può essere utilizzata anche con -i thread; il suo prototipo è: +Di questa funzione esiste anche una versione rientrante, \func{readdir\_r}, +che non usa una struttura allocata staticamente, e può essere utilizzata anche +con i thread; il suo prototipo è: \begin{functions} \headdecl{sys/types.h} \headdecl{dirent.h} @@ -764,25 +764,29 @@ i thread; il suo prototipo La funzione restituisce in \param{result} (come \textit{value result argument}) l'indirizzo dove sono stati salvati i dati, che di norma -corriponde a quallo specificato dall'argomento \param{entry} (anche se non è -assicurato che la funzione usi lo spazio fornito dall'utente). +corriponde a quallo della struttura precedentemente allocata e specificata +dall'argomento \param{entry} (anche se non è assicurato che la funzione usi lo +spazio fornito dall'utente). I vari campi di \struct{dirent} contengono le informazioni relative alle voci -presenti nella directory; i soli campi sempre presenti secondo lo standard -POSIX sono \var{d\_name}, che contiene il nome del file nella forma di una -stringa terminata da uno zero,\footnote{lo standard POSIX non specifica una - lunghezza, ma solo un limite \const{NAME\_MAX}, anche se di norma il valore - massimo per un nome è di 256 byte.} e \var{d\_fileno} che contiene il numero -di inode cui il file è associato (di solito corriponde al campo \var{st\_ino} -di \struct{stat}); questo campo viene anche chiamato \var{d\_ino}, per -compatibilità con la definizione usata da BSD. +presenti nella directory; sia BSD che SVr4\footnote{POSIX prevede invece solo + la presenza del campo \var{d\_fileno}, identico \var{d\_ino}, che in Linux è + definito come alias di quest'ultimo. Il campo \var{d\_name} è considerato + dipendente dall'implementazione.} prevedono che siano sempre presenti il +campo \var{d\_name}, che contiene il nome del file nella forma di una stringa +terminata da uno zero,\footnote{lo standard POSIX non specifica una lunghezza, + ma solo un limite \const{NAME\_MAX}; in SVr4 la lunghezza del campo è + definta come \code{NAME\_MAX+1} che di norma porta al valore di 256 byte + usato anche in Linux.} ed il campo \var{d\_ino}, che contiene il numero di +inode cui il file è associato (di solito corriponde al campo \var{st\_ino} di +\struct{stat}). \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{} struct dirent { - ino_t d_fileno; /* inode number */ + ino_t d_ino; /* inode number */ off_t d_off; /* offset to the next dirent */ unsigned short int d_reclen; /* length of this record */ unsigned char d_type; /* type of file */ @@ -824,11 +828,12 @@ il nome del relativo campo; nel nostro caso sono definite le macro \label{tab:file_dtype_macro} \end{table} -Il campo \var{d\_type} indica il tipo di file (fifo, directory, link -simbolico, ecc.); i suoi possibili valori sono riportati in -\tabref{tab:file_dtype_macro}; per la conversione da e verso l'analogo valore -mantenuto dentro il campo \var{st\_mode} di \struct{stat} sono definite anche -due macro di conversione \macro{IFTODT} e \macro{DTTOIF}: +Per quanto riguarda il significato dei campi opzionali, il campo \var{d\_type} +indica il tipo di file (fifo, directory, link simbolico, ecc.); i suoi +possibili valori sono riportati in \tabref{tab:file_dtype_macro}; per la +conversione da e verso l'analogo valore mantenuto dentro il campo +\var{st\_mode} di \struct{stat} sono definite anche due macro di conversione +\macro{IFTODT} e \macro{DTTOIF}: \begin{functions} \funcdecl{int IFTODT(mode\_t MODE)} Converte il tipo di file dal formato di \var{st\_mode} a quello di \var{d\_type}. @@ -837,10 +842,11 @@ due macro di conversione \macro{IFTODT} e \macro{DTTOIF}: \var{d\_type} a quello di \var{st\_mode}. \end{functions} -Il campo \var{d\_off} contiene la posizione della successiva voce nella -directory, mentre il campo \var{d\_reclen} la lunghezza totale della voce. Con -questi campi diventa possibile spostarsi all'interno dello stream usando la -funzione \func{seekdir},\footnote{sia questa funzione, che la corrispondente +Il campo \var{d\_off} contiene invece la posizione della voce successiva della +directory, mentre il campo \var{d\_reclen} la lunghezza totale della voce +letta. Con questi due campi diventa possibile, determinando la posizione delle +varie voci, spostarsi all'interno dello stream usando la funzione +\func{seekdir},\footnote{sia questa funzione, che la corrispondente \func{telldir}, sono estensioni prese da BSD, non previste dallo standard POSIX.} il cui prototipo è: \begin{prototype}{dirent.h}{void seekdir(DIR *dir, off\_t offset)} @@ -861,8 +867,16 @@ legge la posizione corrente; il prototipo di quest'ultima valore errrato per \param{dir}.} \end{prototype} - - +La sola funzione di posizionamento nello stream prevista dallo standard POSIX +è \funcd{rewinddir}, che riporta la posizione a quella iniziale; il suo +prototipo è: +\begin{functions} + \headdecl{sys/types.h} \headdecl{dirent.h} + + \funcdecl{void rewinddir(DIR *dir)} + + Si posiziona all'inzio di un \textit{directory stream}. +\end{functions} Una volta completate le operazioni si può chiudere il \textit{directory @@ -878,6 +892,68 @@ Una volta completate le operazioni si pu qual caso \var{errno} assume il valore \errval{EBADF}.} \end{functions} +A parte queste funzioni di base in BSD 4.3 è stata introdotta un'altra +funzione che permette di eseguire una scansione completa (con tanto di ricerca +ed ordinamento) del contenuto di una directory; la funzione è +\funcd{scandir}\footnote{in Linux questa funzione è stata introdotta fin dalle + libc4.} ed il suo prototipo è: +\begin{prototype}{dirent.h}{int scandir(const char *dir, + struct dirent ***namelist, int(*select)(const struct dirent *), + int(*compar)(const struct dirent **, const struct dirent **))} + + Esegue una scansione di un \textit{directory stream}. + + \bodydesc{La funzione restituisce in caso di successo il numero di voci + trovate, e -1 altrimenti.} +\end{prototype} + +Al solito, per la presenza fra gli argomenti di due puntatori a funzione, il +prototipo non è molto comprensibile; queste funzioni però sono quelle che +controllano rispettivamente la selezione di una voce (\param{select}) e +l'ordinamento di tutte le voci selezionate (\param{compar}). + +La funzione legge tutte le voci della directory indicata dall'argomento +\param{dir}, passando ciascuna di esse come argomento alla funzione di +\param{select}; se questa ritorna un valore diverso da zero la voce viene +inserita in una struttura allocata dinamicamante con \func{malloc}, qualora si +specifichi un valore \val{NULL} per \func{select} vengono selezionate tutte le +voci. Tutte le voci selezionate vengono poi inserite un una lista (anch'essa +allocata con \func{malloc}, che viene riordinata tramite \func{qsort} usando +la funzione \param{compar} come criterio di ordinamento; alla fine l'indirizzo +della lista ordinata è restituito nell'argomento \param{namelist}. + +Per l'ordinamento sono disponibili anche due funzioni predefinite, +\funcd{alphasort} e \funcd{versionsort}, i cui prototipi sono: +\begin{functions} + \headdecl{dirent.h} + + \funcdecl{int alphasort(const void *a, const void *b)} + + \funcdecl{int versionsort(const void *a, const void *b)} + + Funzioni per l'ordinamento delle voci di \textit{directory stream}. + + \bodydesc{Le funzioni restituiscono un valore minore, uguale o maggiore di + zero qualora il primo argomento sia rispettivamente minore, uguale o + maggiore del secondo.} +\end{functions} + + +La funzione \func{alphasort} deriva da BSD ed è presente in Linux fin dalle +libc4\footnote{la versione delle libc4 e libc5 usa però come argomenti dei + puntatori a delle strutture \struct{dirent}; le glibc usano il prototipo + originario di BSD, mostrato anche nella definizione, che prevede puntatori a + \ctyp{void}.} e deve essere specificata come argomento \param{compare} per +ottenere un ordinamento alfabetico (secondo il valore del campo \var{d\_name} +delle varie voci). Le \acr{glibc} prevedono come estensione\footnote{le glibc, + a partire dalla versione 2.1, effettuano anche l'ordinamento alfabetico + tenendo conto delle varie localizzazioni, usando \func{strcoll} al posto di + \func{strcmp}.} anche \func{versionsort}, che ordina i nomi tenendo conto +del numero di versione (cioè qualcosa per cui \file{file10} viene comunque +dopo \func{file4}.) + + + \subsection{La directory di lavoro} \label{sec:file_work_dir} @@ -1645,21 +1721,21 @@ Esistono varie estensioni a questo modello,\footnote{come le \textit{Access come il \textit{mandatory access control} di SE-Linux.} ma nella maggior parte dei casi il meccanismo standard è più che sufficiente a soddisfare tutte le necessità più comuni. I tre permessi di base associati ad ogni file sono: -\begin{itemize} +\begin{itemize*} \item il permesso di lettura (indicato con la lettera \texttt{r}, dall'inglese \textit{read}). \item il permesso di scrittura (indicato con la lettera \texttt{w}, dall'inglese \textit{write}). \item il permesso di esecuzione (indicato con la lettera \texttt{x}, dall'inglese \textit{execute}). -\end{itemize} +\end{itemize*} mentre i tre livelli su cui sono divisi i privilegi sono: -\begin{itemize} +\begin{itemize*} \item i privilegi per l'utente proprietario del file. \item i privilegi per un qualunque utente faccia parte del gruppo cui appartiene il file. \item i privilegi per tutti gli altri utenti. -\end{itemize} +\end{itemize*} L'insieme dei permessi viene espresso con un numero a 12 bit; di questi i nove meno significativi sono usati a gruppi di tre per indicare i permessi base di @@ -1914,11 +1990,11 @@ invece assunto un uso importante per le directory;\footnote{lo \textsl{sticky impostato un file potrà essere rimosso dalla directory soltanto se l'utente ha il permesso di scrittura su di essa ed inoltre è vera una delle seguenti condizioni: -\begin{itemize} +\begin{itemize*} \item l'utente è proprietario del file \item l'utente è proprietario della directory \item l'utente è l'amministratore -\end{itemize} +\end{itemize*} un classico esempio di directory che ha questo bit impostato è \file{/tmp}, i permessi infatti di solito sono i seguenti: \begin{verbatim} @@ -1946,11 +2022,11 @@ per la creazione di nuove directory (procedimento descritto in Lo standard POSIX prescrive che l'\acr{uid} del nuovo file corrisponda all'userid effettivo del processo che lo crea; per il \acr{gid} invece prevede due diverse possibilità: -\begin{itemize} +\begin{itemize*} \item il \acr{gid} del file corrisponde al groupid effettivo del processo. \item il \acr{gid} del file corrisponde al \acr{gid} della directory in cui esso è creato. -\end{itemize} +\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