Aggiunto esempio di directory scan e iniziato monitor
authorSimone Piccardi <piccardi@gnulinux.it>
Fri, 3 Jan 2003 23:16:05 +0000 (23:16 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Fri, 3 Jan 2003 23:16:05 +0000 (23:16 +0000)
filedir.tex
ipc.tex
sources/DirMonitor.c [new file with mode: 0644]
sources/DirScan.c [new file with mode: 0644]
sources/Makefile
sources/myls.c [new file with mode: 0644]

index e3448ae..efdefa2 100644 (file)
@@ -938,7 +938,6 @@ Per l'ordinamento sono disponibili anche due funzioni predefinite,
     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
@@ -952,7 +951,154 @@ delle varie voci). Le \acr{glibc} prevedono come estensione\footnote{le glibc,
 del numero di versione (cioè qualcosa per cui \file{file10} viene comunque
 dopo \func{file4}.)
 
+Un semplice esempio dell'uso di queste funzioni è riportato in
+\figref{fig:file_my_ls}, dove si è riportata la sezione principale di un
+programma che, usando la routine di scansione illustrata in
+\figref{fig:file_dirscan}, stampa i nomi dei file contenuti in una directory e
+la relativa dimensione (in sostanza una versione semplificata del comando
+\cmd{ls}).
+
+\begin{figure}[!htb]
+  \footnotesize
+  \begin{lstlisting}{}
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>        /* directory */
+#include <stdlib.h>        /* C standard library */
+#include <unistd.h>
+
+/* computation function for DirScan */
+int do_ls(struct dirent * direntry);
+/* main body */
+int main(int argc, char *argv[]) 
+{
+    ...
+    if ((argc - optind) != 1) {          /* There must be remaing parameters */
+        printf("Wrong number of arguments %d\n", argc - optind);
+        usage();
+    }
+    DirScan(argv[1], do_ls);
+    exit(0);
+}
+/*
+ * Routine to print file name and size inside DirScan
+ */
+int do_ls(struct dirent * direntry) 
+{
+    struct stat data;
+
+    stat(direntry->d_name, &data);                          /* get stat data */
+    printf("File: %s \t size: %d\n", direntry->d_name, data.st_size);
+    return 0;
+}
+  \end{lstlisting}
+  \caption{Esempio di codice per eseguire la lista dei file contenuti in una
+    directory.} 
+  \label{fig:file_my_ls}
+\end{figure}
+
+Il programma è estremamente semplice; in \figref{fig:file_my_ls} si è omessa
+la parte di gestione delle opzioni (che prevede solo l'uso di una funzione per
+la stampa della sintassi, anch'essa omessa) ma il codice completo potrà essere
+trovato coi sorgenti allegati nel file \file{myls.c}.
+
+In sostanza tutto quello che fa il programma, dopo aver controllato
+(\texttt{\small 10--13}) di avere almeno un parametro (che indicherà la
+directory da esaminare) è chiamare (\texttt{\small 14}) la funzione
+\func{DirScan} per eseguire la scansione, usando la funzione \code{do\_ls}
+(\texttt{\small 20--26}) per fare tutto il lavoro. 
+
+Quest'ultima si limita (\texttt{\small 23}) a chiamare \func{stat} sul file
+indicato dalla directory entry passata come argomento (il cui nome è appunto
+\var{direntry->d\_name}), memorizzando in una opportuna struttura \var{data} i
+dati ad esso relativi, per poi provvedere (\texttt{\small 24}) a stampare il
+nome del file e la dimensione riportata in \var{data}.  
+
+Dato che la funzione verrà chiamata all'interno di \func{DirScan} per ogni
+voce presente questo è sufficiente a stampare la lista completa dei file e
+delle relative dimensioni.  Si noti infine come si restituisca sempre 0 come
+valore di ritorno per indicare una esecuzione senza errori.
+
+\begin{figure}[!htb]
+  \footnotesize
+  \begin{lstlisting}{}
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>        /* directory */
+#include <stdlib.h>        /* C standard library */
+#include <unistd.h>
+
+/*
+ * Function DirScan: 
+ * 
+ * Input:  the directory name and a computation function
+ * Return: 0 if OK, -1 on errors
+ */
+int DirScan(char * dirname, int(*compute)(struct dirent *)) 
+{
+    DIR * dir;
+    struct dirent *direntry;
+
+    if ( (dir = opendir(dirname)) == NULL) {               /* oper directory */
+        printf("Opening %s\n", dirname);          /* on error print messages */
+        perror("Cannot open directory");                  /* and then return */
+        return -1;
+    }
+    fd = dirfd(dir);                                  /* get file descriptor */
+    fchdir(fd);                                          /* change directory */
+    /* loop on directory entries */
+    while ( (direntry = readdir(dir)) != NULL) {               /* read entry */
+        if (compute(direntry)) {                   /* execute function on it */
+            return -1;                                    /* on error return */
+        }
+    }
+    closedir(dir);
+    return 0;
+}
+
+  \end{lstlisting}
+  \caption{Codice della routine di scansione di una directory contenuta nel
+    file \file{DirScan.c}.} 
+  \label{fig:file_dirscan}
+\end{figure}
 
+Tutto il grosso del lavoro è svolto dalla funzione \func{DirScan}, riportata
+in \figref{fig:file_dirscan}. La funzione è volutamente generica e permette di
+eseguire una funzione, passata come secondo argomento, su tutte le voci di una
+directory.  La funzione inizia con l'aprire (\texttt{\small 19--23}) uno
+stream sulla directory passata come primo argomento, stampando un messaggio in
+caso di errore.
+
+Il passo successivo (\texttt{\small 24--25}) è cambiare directory di lavoro
+(vedi \secref{sec:file_work_dir}), usando in sequenza le funzione \func{dirfd}
+e \func{fchdir} (in realtà si sarebbe potuto usare direttamente \func{chdir}
+su \var{dirname}), in modo che durante il successivo ciclo (\texttt{\small
+  27--31}) sulle singole voci dello stream ci si trovi all'interno della
+directory.\footnote{questo è essenziale al funzionamento della funzione
+  \code{do\_ls} (e ad ogni funzione che debba usare il campo \var{d\_name}, in
+  quanto i nomi dei file memorizzati all'interno di una struttura
+  \struct{dirent} sono sempre relativi alla directory in questione, e senza
+  questo posizionamento non si sarebbe potuto usare \func{stat} per ottenere
+  le dimensioni.}
+
+Avendo usato lo stratagemma di fare eseguire tutte le manipolazioni necessarie
+alla funzione passata come secondo argomento, il ciclo di scansione della
+directory è molto semplice; si legge una voce alla volta (\texttt{\small 27})
+all'interno di una istruzione di \code{while} e fintanto che si riceve una
+voce valida (cioè un puntatore diverso da \val{NULL}) si esegue
+(\texttt{\small 27}) la funzione di elaborazione \var{compare} (che nel nostro
+caso sarà \code{do\_ls}), ritornando con un codice di errore (\texttt{\small
+  28}) qualora questa presenti una anomalia (identificata da un codice di
+ritorno negativo).
+
+Una volta terminato il ciclo la funzione si conclude con la chiusura
+(\texttt{\small 32}) dello stream\footnote{nel nostro caso, uscendo subito
+  dopo la chiamata, questo non servirebbe, in generale però l'operazione è
+  necessaria, dato che la funzione può essere invocata molte volte all'interno
+  dello stesso processo, per cui non chiudere gli stream comporterebbe un
+  consumo progressivo di risorse, con conseguente rischio di esaurimento delle
+  stesse} e la restituzione (\texttt{\small 33}) del codice di operazioni
+concluse con successo.
 
 
 \subsection{La directory di lavoro}
diff --git a/ipc.tex b/ipc.tex
index 09ff74b..c7aa4fc 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -3203,7 +3203,8 @@ caso di errore. Poi si passa ad inizializzare (\texttt{\small 34--38}) la
 struttura \var{lock} per il rilascio del lock, che viene effettuato
 (\texttt{\small 39--42}) subito dopo.
 
- \subsection{Il \textit{memory mapping} anonimo}
+
+\subsection{Il \textit{memory mapping} anonimo}
 \label{sec:ipc_mmap_anonymous}
 
 Abbiamo già visto che quando i processi sono \textsl{correlati}\footnote{se
diff --git a/sources/DirMonitor.c b/sources/DirMonitor.c
new file mode 100644 (file)
index 0000000..c8fad95
--- /dev/null
@@ -0,0 +1,107 @@
+/* DirMonitor.c
+ * 
+ * Copyright (C) 2002 Simone Piccardi
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*****************************************************************************
+ *
+ * File DirMonitor: 
+ *
+ * An example for shared memory use: monitor a directory status,
+ * saving data in a shared memory segment
+ *
+ * Author: S. Piccardi Jan. 2003
+ *
+ * $Id: DirMonitor.c,v 1.1 2003/01/03 23:16:05 piccardi Exp $
+ *
+ *****************************************************************************/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>        /* directory */
+#include <stdlib.h>        /* C standard library */
+#include <unistd.h>
+
+#include "Gapil.h"
+
+/* Help printing routine */
+void usage(void);
+/* computation function for DirScan */
+int ComputeValues(struct dirent * direntry);
+
+/* global variable for shared memory segment */
+int shmid;                                       /* Shared memory identifier */
+
+int main(int argc, char *argv[]) 
+{
+    int i;
+    int mutex;
+    /*
+     * Input section: decode command line parameters 
+     * Use getopt function
+     */
+    opterr = 0;         /* don't want writing to stderr */
+    while ( (i = getopt(argc, argv, "hs:l:wrbf")) != -1) {
+       switch (i) {
+       /* 
+        * Handling options 
+        */ 
+       case 'h':                                            /* help option */
+           printf("Wrong -h option use\n");
+           usage();
+           return -1;
+           break;
+       case '?':                                    /* unrecognized options */
+           printf("Unrecognized options -%c\n",optopt);
+           usage();
+       default:                                       /* should not reached */
+           usage();
+       }
+    }
+    /* ***********************************************************
+     * 
+     *          Options processing completed
+     *
+     *               Main code beginning
+     * 
+     * ***********************************************************/
+    if ((argc - optind) != 1) {          /* There must be remaing parameters */
+       printf("Wrong number of arguments %d\n", argc - optind);
+        usage();
+    }
+    
+    DirScan(argv[1], ComputeValues);
+    exit(0);
+}
+/*
+ * Routine to print file name and size inside DirScan
+ */
+int do_ls(struct dirent * direntry) 
+{
+    struct stat data;
+    stat(direntry->d_name, &data);                          /* get stat data */
+    printf("File: %s \t size: %d\n", direntry->d_name, data.st_size);
+    return 0;
+}
+/*
+ * routine to print usage info and exit
+ */
+void usage(void) {
+    printf("Program myls: list file in a directory \n");
+    printf("Usage:\n");
+    printf("  myls [-h] dirname \n");
+    printf("  -h          print this help\n");
+    exit(1);
+}
diff --git a/sources/DirScan.c b/sources/DirScan.c
new file mode 100644 (file)
index 0000000..38fb555
--- /dev/null
@@ -0,0 +1,63 @@
+/* DirScan.c
+ * 
+ * Copyright (C) 2002 Simone Piccardi
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*****************************************************************************
+ *
+ * File DirScan.c: routine for directory scan 
+ *
+ * Author: S. Piccardi Jan. 2003
+ *
+ * $Id: DirScan.c,v 1.1 2003/01/03 23:16:05 piccardi Exp $
+ *
+ *****************************************************************************/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>        /* directory */
+#include <stdlib.h>        /* C standard library */
+
+/*
+ * Function DirScan: 
+ * 
+ * Scan all entries in a directory, executing the provided function
+ * on each one.
+ *
+ * Input:  the directory name and a computation function
+ * Return: 0 if OK, -1 on errors
+ */
+int DirScan(char * dirname, int(*compute)(struct dirent *)) 
+{
+    DIR * dir;
+    struct dirent *direntry;
+    int fd;
+
+    if ( (dir = opendir(dirname)) == NULL) {               /* oper directory */
+       printf("Opening %s\n", dirname);          /* on error print messages */
+       perror("Cannot open directory");                  /* and then return */
+       return -1;
+    }
+    fd = dirfd(dir);                                  /* get file descriptor */
+    fchdir(fd);                                          /* change directory */
+    /* loop on directory entries */
+    while ( (direntry = readdir(dir)) != NULL) {               /* read entry */
+       if (compute(direntry)) {                   /* execute function on it */
+           return -1;                                    /* on error return */
+       }
+    }
+    closedir(dir);
+    return 0;
+}
index a4e31fd..1311095 100644 (file)
@@ -11,7 +11,7 @@ LIB = libgapil.so
 OBJ = SockRead.o SockWrite.o SigHand.o Mutex.o SharedMem.o LockFile.o
 
 FINAL = forktest errcode echo echod daytimed iterdaytimed daytime testfopen \
-       testren fortune fortuned mqfortune mqfortuned flock
+       testren fortune fortuned mqfortune mqfortuned flock myls
 
 $(LIB): $(OBJ)
        gcc -shared $^ -o $@
@@ -21,6 +21,8 @@ $(OBJ): Gapil.h
 
 all: $(FINAL) $(LIB)
 
+myls: myls.c DirScan.c 
+       $(CC)  $^ -o $@
 
 flock: Flock.c
        $(CC) $(CFLAGJ) $^ -o $@ 
diff --git a/sources/myls.c b/sources/myls.c
new file mode 100644 (file)
index 0000000..bd22144
--- /dev/null
@@ -0,0 +1,102 @@
+/* myls.c
+ * 
+ * Copyright (C) 2002 Simone Piccardi
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*****************************************************************************
+ *
+ * File myls.c: An example ls
+ *
+ * Author: S. Piccardi Jan. 2003
+ *
+ * $Id: myls.c,v 1.1 2003/01/03 23:16:05 piccardi Exp $
+ *
+ *****************************************************************************/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>        /* directory */
+#include <stdlib.h>        /* C standard library */
+#include <unistd.h>
+
+/*
+ * Program myls
+ *
+ * List files and their size inside a given directory
+ */
+/* Help printing routine */
+void usage(void);
+/* computation function for DirScan */
+int do_ls(struct dirent * direntry);
+
+int main(int argc, char *argv[]) 
+{
+    int i;
+    /*
+     * Input section: decode command line parameters 
+     * Use getopt function
+     */
+    opterr = 0;         /* don't want writing to stderr */
+    while ( (i = getopt(argc, argv, "hs:l:wrbf")) != -1) {
+       switch (i) {
+       /* 
+        * Handling options 
+        */ 
+       case 'h':                                            /* help option */
+           printf("Wrong -h option use\n");
+           usage();
+           return -1;
+           break;
+       case '?':                                    /* unrecognized options */
+           printf("Unrecognized options -%c\n",optopt);
+           usage();
+       default:                                       /* should not reached */
+           usage();
+       }
+    }
+    /* ***********************************************************
+     * 
+     *          Options processing completed
+     *
+     *               Main code beginning
+     * 
+     * ***********************************************************/
+    if ((argc - optind) != 1) {          /* There must be remaing parameters */
+       printf("Wrong number of arguments %d\n", argc - optind);
+        usage();
+    }
+    DirScan(argv[1], do_ls);
+    exit(0);
+}
+/*
+ * Routine to print file name and size inside DirScan
+ */
+int do_ls(struct dirent * direntry) 
+{
+    struct stat data;
+    stat(direntry->d_name, &data);                          /* get stat data */
+    printf("File: %s \t size: %d\n", direntry->d_name, data.st_size);
+    return 0;
+}
+/*
+ * routine to print usage info and exit
+ */
+void usage(void) {
+    printf("Program myls: list file in a directory \n");
+    printf("Usage:\n");
+    printf("  myls [-h] dirname \n");
+    printf("  -h          print this help\n");
+    exit(1);
+}