Precedente Successivo

I sorgenti: functions.c

Le applicazioni client e server condividono un certo numero di subroutine che ho raccolto in questo file:

  • select_dir
  • readmsg
  • writemsg
  • readstat
  • writestat
  • Da notare che per le subroutine di trasmissione dei dati sono state aggiunte alcune linee di codice per verificare, in fase di testing, l'effettivo numero di byte trasmessi e/o ricevuti.

    Selettore di file

    Questa funzione è invocata autonomamente dalla funzione scandir() ed è utilizzata per scegliere quali file includere nella lista che scandir() sta costruendo.

    Come richiesto dal testo modificato dell'applicazione, con questa funzione è possibile ignorare tutti i file che non rientrino nella categoria dei "file regolari" o in quella delle "directory", oltre alle directory speciali "." e "..".

    Poiché la struttura passata come argomento è di tipo "direct" ("dirent" nelle librerie non-BSD), si sarebbe potuto utilizzare il campo "d_type" di tale struttura. Purtroppo, però, sulla mia Linux-box il campo risulta sempre vuoto. È stato necessario, allora, ricorrere ancora una volta alla funzione stat().


    #include <stdio.h>
    #include <unistd.h>
    #include <sys/stat.h>
    #include <sys/dir.h>
    
    /*
     * This file collects the common functions
     * shared by server's and client's programs.
     */
    
    #include "defs.h"
    #define DEBUG
    
    extern const char *PRGNAME;
    
    int
    select_dir(struct direct *dir)
    {
    	struct stat file;
    
    	/*
    	 * Selecting function for scandir().
    	 * Only regular files and dir are allowed.
    	 */
    	if (stat(dir->d_name, &file) == -1)
    	{
    		perror("stating in select_dir");
    		return FALSE;
    	}
    	if (S_ISDIR(file.st_mode))
    	{
    		if (strcmp(dir->d_name, ".") != 0
    				&& strcmp(dir->d_name, "..") != 0)
    			return TRUE;
    	}
    	if (S_ISREG(file.st_mode))
    		return TRUE;
    	return FALSE;
    }
    

    Lettura dal socket

    Questa subroutine è stata messa qui allo scopo di alleggerire il codice principale. Il suo scopo, infatti, è semplicemente quello di leggere count byte dal socket sock e riporli nel buffer msg, considerando tutti gli eventuali messaggi d'errore e prestando particolare attenzione all'eventualità che la quantità di dati da ricevere sia inferiore alla dimensione del buffer.


    int
    readmsg(const int sock, char *msg, const size_t count)
    {
    	int rval;
    	
    	/*
    	 * Reads a message msg of count byte from socket sock
    	 * and prints it on stdout if DEBUG is enabled.
    	 */
    #ifdef DEBUG
    	printf("%s: Rcvd:", PRGNAME);
    #endif
    	while ((rval = read(sock, msg, count)) <= 0)
    		if ((rval = read(sock, msg, count)) == -1)
    			perror("reading message from socket");
    #ifdef DEBUG
    	printf(" %-15s (%3u bytes)\n", msg, rval);
    #endif
    	return rval;
    }
    

    Scrittura sul socket

    Questa subroutine è stata messa qui allo scopo di alleggerire il codice principale. Il suo scopo, infatti, è semplicemente quello di scrivere count byte sul socket sock e prendendoli dal buffer msg, considerando tutti gli eventuali messaggi d'errore e prestando particolare attenzione all'eventualità che la quantità di dati da trasmettere sia inferiore alla dimensione del buffer.


    
    int
    writemsg(const int sock, const char *msg, const size_t count)
    {
    	int rval;
    
    	/*
    	 * Writes message msg of count byte from socket sock
    	 * and prints it on stdout if DEBUG is enabled.
    	 */
    #ifdef DEBUG
    	printf("%s: Send:", PRGNAME);
    #endif
    	if ((rval = write(sock, msg, count)) == -1)
    		perror("writing message to socket");
    #ifdef DEBUG
    	printf(" %-15s (%3u bytes)\n", msg, rval);
    #endif
    	return rval;
    }
    

    Lettura di una struttura "stat"

    Anche questa subroutine è stata messa qui allo scopo di alleggerire il codice principale. Il suo scopo consiste nel leggere una struttura di tipo "stat" contenente, fra le altre cose, le informazioni sul tempo dell'ultimo accesso e dell'ultima modifica.


    
    int
    readstat(const int sock, struct stat *filestat)
    {
    	int rval;
    	
    	/*
    	 * Reads stat informations from socket sock
    	 * and prints a log message on stdout if DEBUG is enabled.
    	 */
    #ifdef DEBUG
    	printf("%s: Rcvd:", PRGNAME);
    #endif
    	if ((rval = read(sock, filestat, sizeof(*filestat))) == -1)
    	{
    		perror("receiving file stat");
    		exit(3);
    	}
    #ifdef DEBUG
    	printf(" %-15s (%3u bytes)\n", "File stat", rval);
    #endif
    	return rval;
    }
    

    Scrittura di una struttura "stat"

    È la controparte in scrittura della subroutine precedente.


    
    int
    writestat(const int sock, const struct stat *filestat)
    {
    	int rval;
    	
    	/*
    	 * Writes stat informations to socket sock
    	 * and prints a log message on stdout if DEBUG is enabled.
    	 */
    #ifdef DEBUG
    	printf("%s: Send:", PRGNAME);
    #endif
    	if ((rval = write(sock, filestat, sizeof(*filestat))) == -1)
    	{
    		perror("Sending file stat");
    		exit(3);
    	}
    #ifdef DEBUG
    	printf(" %-15s (%3u bytes)\n", "File stat", rval);
    	sleep(2);
    #endif
    	return rval;
    }
    

    Precedente Successivo