Le applicazioni client e server condividono un certo numero di subroutine che ho raccolto in questo file:
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.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;
}
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;
}
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;
}
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;
}
È 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;
}