Completate le funzioni per la lettura e la scansione delle directory
authorSimone Piccardi <piccardi@gnulinux.it>
Mon, 30 Dec 2002 22:43:30 +0000 (22:43 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Mon, 30 Dec 2002 22:43:30 +0000 (22:43 +0000)
filedir.tex

index 61e39aa..8b522d6 100644 (file)
@@ -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