2022-04-11 19:19:17 +02:00
# define _POSIX_C_SOURCE 200809L
# include <string.h>
2022-04-09 00:37:56 +02:00
# include <errno.h>
2022-04-11 19:19:17 +02:00
# include <inttypes.h>
2022-04-08 21:32:52 +02:00
2022-04-09 00:37:56 +02:00
# include <conn.h>
2022-03-18 20:49:28 +01:00
# include <apiFile.h>
2022-04-09 00:37:56 +02:00
# include <fileQueue.h>
2022-03-31 22:26:44 +02:00
# include <taglialegna.h>
# define MAXLENMESS 512
2022-04-09 22:43:26 +02:00
# define LOGBUFSIZE 2048
2022-03-31 22:26:44 +02:00
# define MEOK "20" //OK
2022-04-22 21:59:40 +02:00
// #define ME "21" // not used
2022-03-31 22:26:44 +02:00
// #define ME "22" // not used
# define MEFP "25" // file purged
// #define ME "40" // not used
// #define ME "41" // not used
# define MESD "42" // shutting down
# define MENT "45" // requested file action not taken
# define MESY "50" // syntax error
// #define ME "51" // not used
// #define ME "52" // not used
# define MESE "55" // server error
2022-04-04 18:58:40 +02:00
// -----------------------------------------------------------------------------
/* funzioni ausiliarie */
2022-04-08 21:32:52 +02:00
// invio il messaggio al client e poi l'errno
void serror ( char * m , long fd_c , taglia_t * taglia , char * mlog ) {
if ( ! m ) {
errno = EINVAL ;
m = MESY ;
}
2022-04-27 21:18:25 +02:00
if ( writen ( fd_c , m , strnlen ( m , MAXLENMESS ) ) < 0 ) {
2022-04-08 21:32:52 +02:00
perror ( " writen " ) ;
goto _serror_cleanup ;
}
if ( writen ( fd_c , & errno , sizeof ( errno ) ) < 0 ) {
perror ( " writen " ) ;
goto _serror_cleanup ;
}
if ( taglia_write ( taglia , mlog ) < 0 )
goto _serror_cleanup ;
return ;
_serror_cleanup :
return ;
}
2022-04-04 18:58:40 +02:00
// invio il messaggio al client
void sendMessage ( char * m , long fd_c , taglia_t * taglia , char * mlog ) {
if ( ! m ) {
m = MEOK ;
}
2022-04-24 01:36:43 +02:00
if ( writen ( fd_c , m , strnlen ( m , MAXLENMESS ) ) < 0 ) {
2022-04-04 18:58:40 +02:00
perror ( " writen " ) ;
goto _sendM_cleanup ;
}
if ( taglia_write ( taglia , mlog ) < 0 )
goto _sendM_cleanup ;
return ;
_sendM_cleanup :
return ;
}
2022-04-10 20:51:43 +02:00
// invia un file
int sendFile ( fileT * f , long fd_c , taglia_t * taglia ) {
if ( ! f | | ! taglia ) {
errno = EINVAL ;
return - 1 ;
}
// send filepath dimension, then filepath
int64_t filepathLength = ( int64_t ) strnlen ( f - > filepath , MAXLENMESS ) + 1 ;
if ( writen ( fd_c , & filepathLength , sizeof ( filepathLength ) ) < 0 ) {
perror ( " writen " ) ;
return - 1 ;
}
if ( writen ( fd_c , f - > filepath , ( size_t ) filepathLength ) < 0 ) {
perror ( " writen " ) ;
return - 1 ;
}
// send file dimension, then file
int64_t validLength = ( int64_t ) f - > valid ;
if ( writen ( fd_c , & validLength , sizeof ( validLength ) ) < 0 ) {
perror ( " writen " ) ;
return - 1 ;
}
if ( writen ( fd_c , f - > data , f - > valid ) < 0 ) {
perror ( " writen " ) ;
return - 1 ;
}
char tmp_log [ LOGBUFSIZE ] ;
int n = 0 ;
size_t m = sizeof ( tmp_log ) ;
2022-04-11 19:19:17 +02:00
n + = snprintf ( tmp_log + n , m - n , " File \" %s \" , di dimensione % " PRId64 " Bytes al client %ld . \n " , f - > filepath , validLength , fd_c ) ;
2022-04-10 20:51:43 +02:00
if ( taglia_write ( taglia , tmp_log ) < 0 ) {
perror ( " taglia_write " ) ;
return 1 ;
}
return 0 ;
}
2022-04-04 18:58:40 +02:00
// invio il messaggio al client e poi il file
void sendMessageFile ( char * m , fileT * f , long fd_c , taglia_t * taglia , char * mlog ) {
if ( ! f ) {
errno = EINVAL ;
2022-04-09 22:43:26 +02:00
char errmlog [ 2 * LOGBUFSIZE ] = " Errore negli argomenti alla funzione sendMessagefile (fileT == NULL). Messaggio originale: \n \t " ;
2022-04-08 21:32:52 +02:00
strncat ( errmlog , mlog , sizeof ( errmlog ) - strlen ( errmlog ) - 1 ) ;
serror ( MESY , fd_c , taglia , errmlog ) ;
2022-04-04 18:58:40 +02:00
goto _sendMF_cleanup ;
}
if ( ! m ) {
2022-04-08 21:32:52 +02:00
m = MEFP ;
2022-04-04 18:58:40 +02:00
}
2022-04-27 21:18:25 +02:00
if ( writen ( fd_c , m , strnlen ( m , MAXLENMESS ) ) < 0 ) {
2022-04-04 18:58:40 +02:00
perror ( " writen " ) ;
goto _sendMF_cleanup ;
}
2022-04-27 21:18:25 +02:00
int64_t * n = calloc ( 1 , sizeof ( * n ) ) ;
if ( n = = NULL ) {
perror ( " calloc " ) ;
goto _sendMF_cleanup ;
}
* n = 1 ;
if ( writen ( fd_c , n , sizeof ( int64_t ) ) < 0 ) {
2022-04-22 21:59:40 +02:00
perror ( " writen " ) ;
goto _sendMF_cleanup ;
}
2022-04-27 21:18:25 +02:00
free ( n ) ;
2022-04-04 18:58:40 +02:00
if ( sendFile ( f , fd_c , taglia ) < 0 ) {
perror ( " sendFile " ) ;
goto _sendMF_cleanup ;
}
2022-04-10 20:51:43 +02:00
if ( taglia_write ( taglia , mlog ) < 0 ) {
perror ( " log write " ) ;
2022-04-04 18:58:40 +02:00
goto _sendMF_cleanup ;
2022-04-10 20:51:43 +02:00
}
2022-04-04 18:58:40 +02:00
return ;
_sendMF_cleanup :
return ;
}
// invio il messaggio al client e poi n file
2022-04-08 21:32:52 +02:00
void sendMessageFileN ( char * m , fileT * * f , int n , long fd_c , taglia_t * taglia , char * mlog ) {
2022-04-04 18:58:40 +02:00
if ( ! f ) {
errno = EINVAL ;
2022-04-09 22:43:26 +02:00
char errmlog [ 2 * LOGBUFSIZE ] = " Errore negli argomenti alla funzione sendMessagefile (fileT == NULL). Messaggio originale: \n \t " ;
2022-04-08 21:32:52 +02:00
strncat ( errmlog , mlog , sizeof ( errmlog ) - strlen ( errmlog ) - 1 ) ;
serror ( MESY , fd_c , taglia , errmlog ) ;
2022-04-04 18:58:40 +02:00
goto _sendMFN_cleanup ;
}
if ( ! m ) {
2022-04-08 21:32:52 +02:00
m = MEFP ;
2022-04-04 18:58:40 +02:00
}
2022-04-27 21:18:25 +02:00
if ( writen ( fd_c , m , strnlen ( m , MAXLENMESS ) ) < 0 ) {
2022-04-04 18:58:40 +02:00
perror ( " writen " ) ;
2022-04-08 21:32:52 +02:00
goto _sendMFN_cleanup ;
2022-04-04 18:58:40 +02:00
}
2022-04-22 21:59:40 +02:00
if ( write ( fd_c , & n , sizeof ( n ) ) < 0 ) {
perror ( " writen " ) ;
goto _sendMFN_cleanup ;
}
2022-04-04 18:58:40 +02:00
for ( int i = 0 ; i < n & & ( f [ i ] ! = NULL ) ; + + i ) {
if ( sendFile ( f [ i ] , fd_c , taglia ) < 0 ) {
perror ( " sendFile " ) ;
2022-04-08 21:32:52 +02:00
goto _sendMFN_cleanup ;
2022-04-04 18:58:40 +02:00
}
}
if ( taglia_write ( taglia , mlog ) < 0 )
2022-04-08 21:32:52 +02:00
goto _sendMFN_cleanup ;
2022-04-04 18:58:40 +02:00
return ;
_sendMFN_cleanup :
return ;
}
2022-03-31 22:26:44 +02:00
2022-04-10 20:51:43 +02:00
// -----------------------------------------------------------------------------
2022-03-31 22:26:44 +02:00
void openFile ( char * filepath , int flags , queueT * q , long fd_c , taglia_t * taglia ) {
// messaggio da scrivere sul logfile
2022-04-09 22:43:26 +02:00
char tmp_buf [ LOGBUFSIZE ] ;
2022-03-31 22:26:44 +02:00
int n = 0 ;
size_t m = sizeof ( tmp_buf ) ;
if ( ! filepath | | ! q | | ! taglia ) {
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una openFile (flags = %x) sul file \" %s \" e' terminata con errore \n " , fd_c , flags , filepath ) ;
errno = EINVAL ;
serror ( MESY , fd_c , taglia , tmp_buf ) ;
return ;
}
int found = searchFile ( q , filepath ) ; // cerco il file nella queue
2022-04-27 21:18:25 +02:00
int create = ( flags & C_CREATE ) ? 1 : 0 ; // also %2
int lock = ( flags & C_LOCK ) ? 1 : 0 ; // also >>1%2
2022-03-31 22:26:44 +02:00
fileT * removed = NULL ; // file che è stato rimosso
if ( found & & create ) { // si vuole creare il file ma esiste già
2022-04-24 01:36:43 +02:00
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una openFile (flags = %x) sul file \" %s \" ma il file esiste già \n " , fd_c , flags , filepath ) ;
2022-03-31 22:26:44 +02:00
errno = EEXIST ;
serror ( MENT , fd_c , taglia , tmp_buf ) ;
return ;
}
if ( ! found & & ! create ) { // si vuole aprire e non creare un file inesistente
2022-04-24 01:36:43 +02:00
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una openFile (flags = %x) sul file \" %s \" ma il file non esiste \n " , fd_c , flags , filepath ) ;
2022-03-31 22:26:44 +02:00
errno = ENOENT ;
serror ( MENT , fd_c , taglia , tmp_buf ) ;
return ;
}
if ( found & & ! create ) {
2022-04-08 21:32:52 +02:00
if ( openFileInQueue ( q , filepath , lock , fd_c ) = = - 1 ) {
2022-04-24 01:36:43 +02:00
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una openFile (flags = %x) sul file \" %s \" e' terminato con errore del server \n " , fd_c , flags , filepath ) ;
2022-03-31 22:26:44 +02:00
perror ( " openFileInQueue " ) ;
serror ( MESE , fd_c , taglia , tmp_buf ) ;
return ;
}
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una openFile (flags = %x) sul file \" %s \" e' terminata con successo \n " , fd_c , flags , filepath ) ;
sendMessage ( MEOK , fd_c , taglia , tmp_buf ) ;
return ;
}
if ( ! found & & create ) { // not found and creating new file
2022-04-08 21:32:52 +02:00
if ( getLen ( q ) = = q - > maxLen ) { // capacity miss
2022-03-31 22:26:44 +02:00
removed = dequeue ( q ) ;
if ( ! removed ) {
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una openFile (flags = %x) sul file \" %s \" e' terminato con errore \n " , fd_c , flags , filepath ) ;
perror ( " dequeue " ) ;
serror ( MESE , fd_c , taglia , tmp_buf ) ;
return ;
}
fileT * f = createFileT ( filepath , lock , fd_c , 1 ) ; // create new file
if ( ! f ) {
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una openFile (flags = %x) sul file \" %s \" e' terminato con errore del server \n " , fd_c , flags , filepath ) ;
perror ( " createFileT " ) ;
2022-04-08 21:32:52 +02:00
serror ( MESE , fd_c , taglia , tmp_buf ) ;
2022-03-31 22:26:44 +02:00
return ;
}
if ( enqueue ( q , f ) ! = 0 ) {
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una openFile (flags = %x) sul file \" %s \" e' terminato con errore del server \n " , fd_c , flags , filepath ) ;
perror ( " enqueue " ) ;
2022-04-08 21:32:52 +02:00
serror ( MESE , fd_c , taglia , tmp_buf ) ;
2022-03-31 22:26:44 +02:00
return ;
}
taglia_update ( taglia , q , 1 ) ; // removed only one file
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una openFile (flags = %x) sul file \" %s \" ha causato una capacity miss. File espulso \" %s \" \n " , fd_c , flags , filepath , removed - > filepath ) ;
sendMessageFile ( MEFP , removed , fd_c , taglia , tmp_buf ) ;
free ( removed ) ;
return ;
}
fileT * f = createFileT ( filepath , lock , fd_c , 1 ) ;
if ( ! f ) {
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una openFile (flags = %x) sul file \" %s \" e' terminato con errore del server \n " , fd_c , flags , filepath ) ;
perror ( " createFileT " ) ;
2022-04-08 21:32:52 +02:00
serror ( MESE , fd_c , taglia , tmp_buf ) ;
2022-03-31 22:26:44 +02:00
return ;
}
if ( enqueue ( q , f ) ! = 0 ) {
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una openFile (flags = %x) sul file \" %s \" e' terminato con errore del server \n " , fd_c , flags , filepath ) ;
perror ( " enqueue " ) ;
2022-04-08 21:32:52 +02:00
serror ( MESE , fd_c , taglia , tmp_buf ) ;
2022-03-31 22:26:44 +02:00
return ;
}
// abbiamo aggiunto un file quindi il numero di file è cambiato
// quindi bisogna fare un update del log
taglia_update ( taglia , q , 0 ) ;
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una openFile (flags = %x) sul file \" %s \" e' terminato con successo \n " , fd_c , flags , filepath ) ;
sendMessage ( MEOK , fd_c , taglia , tmp_buf ) ;
return ;
}
2022-04-09 01:11:46 +02:00
// codice non raggiungibile
return ;
2022-03-31 22:26:44 +02:00
}
2022-04-04 18:58:40 +02:00
void readFile ( char * filepath , queueT * q , long fd_c , taglia_t * taglia ) {
// messaggio da scrivere sul logfile
2022-04-09 22:43:26 +02:00
char tmp_buf [ LOGBUFSIZE ] ;
2022-04-04 18:58:40 +02:00
int n = 0 ;
size_t m = sizeof ( tmp_buf ) ;
if ( ! filepath | | ! q | | ! taglia ) {
2022-04-25 20:24:55 +02:00
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una readFile sul file \" %s \" e' terminata con errore del server \n " , fd_c , filepath ) ;
2022-04-04 18:58:40 +02:00
errno = EINVAL ;
serror ( MESY , fd_c , taglia , tmp_buf ) ;
return ;
2022-03-31 22:26:44 +02:00
}
2022-04-04 18:58:40 +02:00
fileT * f = NULL ;
f = find ( q , filepath ) ;
if ( ! f ) {
2022-04-25 20:24:55 +02:00
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una readFile sul file \" %s \" ma il file non esiste \n " , fd_c , filepath ) ;
2022-04-04 18:58:40 +02:00
errno = ENOENT ;
serror ( MESE , fd_c , taglia , tmp_buf ) ;
return ;
}
2022-03-31 22:26:44 +02:00
2022-04-27 21:18:25 +02:00
if ( f - > open = = 0 ) { // file not already open
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una readFile sul file \" %s \" e' terminata con errore, file non aperto \n " , fd_c , filepath ) ;
2022-04-04 18:58:40 +02:00
errno = EPERM ;
serror ( MENT , fd_c , taglia , tmp_buf ) ;
destroyFile ( f ) ; // f is a copy so we need to cleen up
return ;
}
2022-03-31 22:26:44 +02:00
2022-04-08 21:32:52 +02:00
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una readFile sul file \" %s \" e' terminata con successo \n " , fd_c , filepath ) ;
2022-04-04 18:58:40 +02:00
sendMessageFile ( MEOK , f , fd_c , taglia , tmp_buf ) ;
destroyFile ( f ) ; // f is a copy so we need to cleen up
2022-03-31 22:26:44 +02:00
return ;
}
2022-04-04 18:58:40 +02:00
2022-04-09 22:43:26 +02:00
void readNFiles ( int num , queueT * q , long fd_c , taglia_t * taglia ) {
// messaggio da scrivere sul logfile
char tmp_buf [ LOGBUFSIZE ] ;
int n = 0 ;
size_t m = sizeof ( tmp_buf ) ;
if ( ! q | | ! taglia ) {
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una readNFile (n = %d) e' terminata con errore \n " , fd_c , num ) ;
errno = EINVAL ;
serror ( MESY , fd_c , taglia , tmp_buf ) ;
return ;
}
int oldNum = num ;
num = ( num < = 0 | | num > getLen ( q ) ) ? getLen ( q ) : num ;
fileT * * toSend = calloc ( num , sizeof ( fileT * ) ) ;
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una readNFile (n = %d) e' terminata con successo. File inviati: \n " , fd_c , num ) ;
// extract n files, we dont check if the client can actually modify
// the files since we add them back immediatly
for ( int i = 0 ; i < num ; + + i ) { /* TODO: fix here */
toSend [ i ] = dequeue ( q ) ;
if ( ! toSend [ i ] ) {
n = 0 ;
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una readNFiles (n = %d) e' terminato con errore del server \n " , fd_c , oldNum ) ;
perror ( " dequeue " ) ;
serror ( MESE , fd_c , taglia , tmp_buf ) ;
return ;
}
int tmp = enqueue ( q , toSend [ i ] ) ;
if ( tmp < 0 ) {
n = 0 ;
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una readNFiles (n = %d) e' terminato con errore del server \n " , fd_c , oldNum ) ;
perror ( " enqueue " ) ;
serror ( MESE , fd_c , taglia , tmp_buf ) ;
return ;
}
n + = snprintf ( tmp_buf + n , m - n , " \t %d) \" %s \" \n " , i , toSend [ i ] - > filepath ) ;
}
sendMessageFileN ( MEOK , toSend , num , fd_c , taglia , tmp_buf ) ;
free ( toSend ) ;
2022-04-04 22:31:14 +02:00
return ;
}
2022-04-04 18:58:40 +02:00
void writeFile ( char * filepath , size_t size , queueT * q , long fd_c , taglia_t * taglia , int append ) {
// messaggio da scrivere sul logfile
2022-04-09 22:43:26 +02:00
char tmp_buf [ LOGBUFSIZE ] ;
2022-04-04 18:58:40 +02:00
int n = 0 ;
size_t m = sizeof ( tmp_buf ) ;
if ( ! filepath | | ! q | | ! taglia ) {
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una writeFile (append = %x) sul file \" %s \" e' terminata con errore \n " , fd_c , append , filepath ) ;
2022-03-31 22:26:44 +02:00
errno = EINVAL ;
2022-04-04 18:58:40 +02:00
serror ( MESY , fd_c , taglia , tmp_buf ) ;
return ;
2022-03-31 22:26:44 +02:00
}
2022-04-27 21:18:25 +02:00
2022-04-09 01:11:46 +02:00
// cerco il file
2022-04-04 18:58:40 +02:00
fileT * f = NULL ;
f = find ( q , filepath ) ;
2022-04-27 21:18:25 +02:00
2022-04-04 18:58:40 +02:00
if ( ! f ) { // file is not present
2022-04-24 01:36:43 +02:00
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una writeFile (append = %x) sul file \" %s \" , dimensione = %ld, e' terminata con errore, file non trovato \n " , fd_c , append , filepath , size ) ;
2022-04-04 18:58:40 +02:00
errno = ENOENT ;
serror ( MENT , fd_c , taglia , tmp_buf ) ;
destroyFile ( f ) ;
return ;
2022-03-31 22:26:44 +02:00
}
2022-03-18 20:49:28 +01:00
2022-04-24 01:36:43 +02:00
// file non aperto || non append e nessuna lock || lock ma non si è proprietari
if ( ! f - > open | | ( ! append & & ! f - > O_LOCK ) | | ( f - > O_LOCK & & f - > owner ! = fd_c ) ) {
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una writeFile (append = %x) sul file \" %s \" , dimensione = %ld, e' terminata con errore, non proprietario del file \n " , fd_c , append , filepath , size ) ;
2022-04-04 18:58:40 +02:00
errno = EPERM ;
serror ( MENT , fd_c , taglia , tmp_buf ) ;
destroyFile ( f ) ;
return ;
2022-03-31 22:26:44 +02:00
}
2022-04-24 01:36:43 +02:00
long trueSizeAdded = 0 ; // we may have alredy some space allocated
2022-04-04 18:58:40 +02:00
if ( append ) {
trueSizeAdded = size - f - > size + f - > valid ;
} else {
trueSizeAdded = ( size > f - > size ) ? size - f - > size : 0 ;
}
destroyFile ( f ) ; // not needed anymore
2022-03-18 20:49:28 +01:00
2022-04-24 01:36:43 +02:00
if ( trueSizeAdded + getSize ( q ) > q - > maxSize ) {
// writing would be more than capacity
fileT * * removed = NULL ; // array that may (worst case) hold all files to be sent to the client
2022-04-04 18:58:40 +02:00
removed = dequeueN ( q , filepath , trueSizeAdded ) ;
if ( ! removed ) { // internal error
2022-04-24 01:36:43 +02:00
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una writeFile (append = %x) sul file \" %s \" , dimensione = %ld, e' terminata con errore del server \n " , fd_c , append , filepath , size ) ;
2022-04-04 18:58:40 +02:00
errno = ENOENT ;
serror ( MESY , fd_c , taglia , tmp_buf ) ;
return ;
}
int ln = 0 ;
fileT * tmp = removed [ ln ] ;
2022-04-24 01:36:43 +02:00
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una writeFile (append = %x) sul file \" %s \" , dimensione = %ld, e' terminata con successo, allocando %ld B in memoria. Ha causato una capacity miss e ha fatto espellere i seguenti file: " , fd_c , append , filepath , size , trueSizeAdded ) ;
2022-04-04 18:58:40 +02:00
while ( tmp ! = NULL ) {
n + = snprintf ( tmp_buf + n , m - n , " \" %s \" " , tmp - > filepath ) ;
+ + ln ;
tmp = removed [ ln ] ;
}
n + = snprintf ( tmp_buf + n , m - n , " \n " ) ;
taglia_update ( taglia , q , ln ) ;
2022-03-18 20:49:28 +01:00
2022-04-04 18:58:40 +02:00
sendMessageFileN ( MEFP , removed , ln , fd_c , taglia , tmp_buf ) ;
for ( int i = 0 ; i < ln & & ( removed [ i ] ! = NULL ) ; + + i ) {
destroyFile ( removed [ i ] ) ;
}
free ( removed ) ;
2022-03-18 20:49:28 +01:00
2022-04-24 01:36:43 +02:00
// now we can get the actual file
2022-04-04 18:58:40 +02:00
void * content = NULL ;
2022-04-24 01:36:43 +02:00
content = calloc ( size , sizeof ( char ) ) ;
2022-04-04 18:58:40 +02:00
if ( ! content ) {
2022-04-24 01:36:43 +02:00
perror ( " calloc " ) ;
2022-04-04 18:58:40 +02:00
return ;
}
if ( ( readn ( fd_c , content , size ) ) = = - 1 ) {
perror ( " readn " ) ;
return ;
}
2022-03-18 20:49:28 +01:00
2022-04-24 01:36:43 +02:00
n = 0 ;
2022-04-04 18:58:40 +02:00
if ( append ) {
if ( appendFileInQueue ( q , filepath , content , size , fd_c ) = = - 1 ) {
2022-04-24 01:36:43 +02:00
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una writeFile (append = %x) sul file \" %s \" , dimensione = %ld, errore del server \n " , fd_c , append , filepath , size ) ;
serror ( MESY , fd_c , taglia , tmp_buf ) ;
2022-04-04 18:58:40 +02:00
perror ( " appendFileInQueue " ) ;
2022-04-08 21:32:52 +02:00
free ( content ) ;
2022-04-04 18:58:40 +02:00
return ;
}
} else {
if ( writeFileInQueue ( q , filepath , content , size , fd_c ) = = - 1 ) {
2022-04-24 01:36:43 +02:00
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una writeFile (append = %x) sul file \" %s \" , dimensione = %ld, errore del server \n " , fd_c , append , filepath , size ) ;
serror ( MESY , fd_c , taglia , tmp_buf ) ;
2022-04-04 18:58:40 +02:00
perror ( " writeFileInQueue " ) ;
2022-04-08 21:32:52 +02:00
free ( content ) ;
2022-04-04 18:58:40 +02:00
return ;
}
}
2022-03-18 20:49:28 +01:00
2022-04-24 01:36:43 +02:00
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una writeFile (append = %x) sul file \" %s \" , dimensione = %ld, e' terminata con successo \n " , fd_c , append , filepath , size ) ;
sendMessage ( MEOK , fd_c , taglia , tmp_buf ) ;
2022-04-04 18:58:40 +02:00
taglia_update ( taglia , q , 0 ) ;
2022-04-08 21:32:52 +02:00
free ( content ) ;
2022-04-04 18:58:40 +02:00
return ;
}
2022-04-24 01:36:43 +02:00
// no dequeue
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una writeFile (append = %x) sul file \" %s \" , dimensione = %ld, accettata la richiesta. \n " , fd_c , append , filepath , size ) ;
sendMessage ( MEOK , fd_c , taglia , tmp_buf ) ;
2022-04-04 18:58:40 +02:00
// non c'è ancora bisogno di rimuovere file
void * content = NULL ;
2022-04-24 01:36:43 +02:00
content = calloc ( size , sizeof ( char ) ) ;
2022-04-04 18:58:40 +02:00
if ( ! content ) {
2022-04-24 01:36:43 +02:00
perror ( " calloc " ) ;
2022-04-04 18:58:40 +02:00
return ;
}
if ( readn ( fd_c , content , size ) = = - 1 ) {
perror ( " readn " ) ;
return ;
}
2022-03-18 20:49:28 +01:00
2022-04-24 01:36:43 +02:00
n = 0 ;
2022-03-18 20:49:28 +01:00
2022-04-04 18:58:40 +02:00
if ( append ) {
if ( appendFileInQueue ( q , filepath , content , size , fd_c ) = = - 1 ) {
2022-04-24 01:36:43 +02:00
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una writeFile (append = %x) sul file \" %s \" , dimensione = %ld, errore del server \n " , fd_c , append , filepath , size ) ;
serror ( MESY , fd_c , taglia , tmp_buf ) ;
2022-04-04 18:58:40 +02:00
perror ( " appendFileInQueue " ) ;
2022-04-08 21:32:52 +02:00
free ( content ) ;
2022-04-04 18:58:40 +02:00
return ;
}
} else {
if ( writeFileInQueue ( q , filepath , content , size , fd_c ) = = - 1 ) {
2022-04-24 01:36:43 +02:00
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una writeFile (append = %x) sul file \" %s \" , dimensione = %ld, errore del server \n " , fd_c , append , filepath , size ) ;
serror ( MESY , fd_c , taglia , tmp_buf ) ;
2022-04-04 18:58:40 +02:00
perror ( " writeFileInQueue " ) ;
2022-04-08 21:32:52 +02:00
free ( content ) ;
2022-04-04 18:58:40 +02:00
return ;
}
}
2022-04-24 01:36:43 +02:00
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una writeFile (append = %x) sul file \" %s \" , dimensione = %ld, e' terminata con successo \n " , fd_c , append , filepath , size ) ;
sendMessage ( MEOK , fd_c , taglia , tmp_buf ) ;
2022-03-18 20:49:28 +01:00
2022-04-04 18:58:40 +02:00
taglia_update ( taglia , q , 0 ) ;
2022-03-18 20:49:28 +01:00
2022-04-08 21:32:52 +02:00
free ( content ) ;
2022-04-04 18:58:40 +02:00
return ;
}
2022-03-18 20:49:28 +01:00
2022-04-08 21:32:52 +02:00
void lockFile ( char * filepath , queueT * q , long fd_c , taglia_t * taglia , pthread_mutex_t * lock , waiting_t * * waiting ) {
2022-04-09 01:11:46 +02:00
// messaggio da scrivere sul logfile
2022-04-09 22:43:26 +02:00
char tmp_buf [ LOGBUFSIZE ] ;
2022-04-09 01:11:46 +02:00
int n = 0 ;
size_t m = sizeof ( tmp_buf ) ;
if ( ! filepath | | ! q | | ! taglia | | ! lock | | ! waiting ) {
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una lockFile sul file \" %s \" e' terminata con errore. \n " , fd_c , filepath ) ;
errno = EINVAL ;
serror ( MESY , fd_c , taglia , tmp_buf ) ;
return ;
}
// cerco il file da impostare in modalita' locked
fileT * f = NULL ;
f = find ( q , filepath ) ;
if ( ! f ) { // file is not present
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una lockFile sul file \" %s \" ma risulta assente. \n " , fd_c , filepath ) ;
errno = ENOENT ;
serror ( MENT , fd_c , taglia , tmp_buf ) ;
destroyFile ( f ) ;
return ;
}
// provo a prendere la lock
if ( openFileInQueue ( q , filepath , 1 , fd_c ) = = - 1 ) {
// non siamo riusciti a prendere la lock al file, quindi aspettiamo che
// venga rilasciata mettendoci in attesa nella waiting list
if ( errno = = EPERM ) {
if ( pthread_mutex_lock ( lock ) = = - 1 ) { // begin ME
perror ( " lock " ) ;
destroyFile ( f ) ;
return ;
}
if ( addWaiting ( waiting , filepath , fd_c ) = = - 1 ) {
perror ( " addWaiting " ) ;
pthread_mutex_unlock ( lock ) ;
destroyFile ( f ) ;
return ;
}
if ( pthread_mutex_unlock ( lock ) = = - 1 ) { // end ME
perror ( " unlock " ) ;
}
destroyFile ( f ) ;
return ;
}
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una lockFile sul file \" %s \" e' terminata con errore. \n " , fd_c , filepath ) ;
errno = ENOLCK ;
serror ( MESE , fd_c , taglia , tmp_buf ) ;
destroyFile ( f ) ;
return ;
}
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una lockFile sul file \" %s \" e' terminata con successo \n " , fd_c , filepath ) ;
sendMessage ( MEOK , fd_c , taglia , tmp_buf ) ;
destroyFile ( f ) ;
2022-04-04 22:31:14 +02:00
return ;
}
2022-03-18 20:49:28 +01:00
2022-04-08 21:32:52 +02:00
void unlockFile ( char * filepath , queueT * q , long fd_c , taglia_t * taglia , pthread_mutex_t * lock , waiting_t * * waiting ) {
2022-04-10 20:51:43 +02:00
// messaggio da scrivere sul logfile
char tmp_buf [ LOGBUFSIZE ] ;
int n = 0 ;
size_t m = sizeof ( tmp_buf ) ;
if ( ! filepath | | ! q | | ! taglia | | ! lock | | ! waiting ) {
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una unlockFile sul file \" %s \" e' terminata con errore. \n " , fd_c , filepath ) ;
errno = EINVAL ;
serror ( MESY , fd_c , taglia , tmp_buf ) ;
return ;
}
// cerco il file su cui rilasciare la lock
if ( ! searchFile ( q , filepath ) ) { // file e' assente
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una unlockFile sul file \" %s \" ma risulta assente. \n " , fd_c , filepath ) ;
errno = ENOENT ;
serror ( MENT , fd_c , taglia , tmp_buf ) ;
return ;
}
if ( unlockFileInQueue ( q , filepath , fd_c ) ! = 0 ) {
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una unlockFile sul file \" %s \" ma non è stata rilasciata la lock. \n " , fd_c , filepath ) ;
serror ( MENT , fd_c , taglia , tmp_buf ) ;
return ;
}
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una unlockFile sul file \" %s \" e' terminata con successo \n " , fd_c , filepath ) ;
sendMessage ( MEOK , fd_c , taglia , tmp_buf ) ;
// segnalo a un client in lista d'attesa che una lock e' stata rilasciata
if ( pthread_mutex_lock ( lock ) = = - 1 ) { // begin ME
perror ( " lock " ) ;
return ;
}
int waked = - 1 ;
waked = removeFirstWaiting ( waiting , filepath ) ;
if ( waked ! = - 1 ) {
// we lock the file for the other client
lockFile ( filepath , q , waked , taglia , lock , waiting ) ;
}
if ( pthread_mutex_unlock ( lock ) = = - 1 ) { // end ME
perror ( " unlock " ) ;
return ;
}
2022-04-04 22:31:14 +02:00
return ;
}
2022-03-18 20:49:28 +01:00
2022-03-31 22:26:44 +02:00
2022-04-08 21:32:52 +02:00
void closeFile ( char * filepath , queueT * q , long fd_c , taglia_t * taglia , pthread_mutex_t * lock , waiting_t * * waiting ) {
2022-04-10 20:51:43 +02:00
// messaggio da scrivere sul logfile
char tmp_buf [ LOGBUFSIZE ] ;
int n = 0 ;
size_t m = sizeof ( tmp_buf ) ;
if ( ! filepath | | ! q | | ! taglia | | ! lock | | ! waiting ) {
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una closeFile sul file \" %s \" e' terminata con errore. \n " , fd_c , filepath ) ;
errno = EINVAL ;
serror ( MESY , fd_c , taglia , tmp_buf ) ;
return ;
}
// cerco il file da chiudere
if ( ! searchFile ( q , filepath ) ) { // file e' assente
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una closeFile sul file \" %s \" ma risulta assente. \n " , fd_c , filepath ) ;
errno = ENOENT ;
serror ( MENT , fd_c , taglia , tmp_buf ) ;
return ;
}
if ( closeFileInQueue ( q , filepath , fd_c ) = = - 1 ) {
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una closeFile sul file \" %s \" e' terminata con errore. \n " , fd_c , filepath ) ;
serror ( MENT , fd_c , taglia , tmp_buf ) ;
return ;
}
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una closeFile sul file \" %s \" e' terminata con successo \n " , fd_c , filepath ) ;
sendMessage ( MEOK , fd_c , taglia , tmp_buf ) ;
// segnalo a un client in lista d'attesa che una lock e' stata rilasciata
if ( pthread_mutex_lock ( lock ) = = - 1 ) { // begin ME
perror ( " lock " ) ;
return ;
}
int waked = - 1 ;
waked = removeFirstWaiting ( waiting , filepath ) ;
if ( waked ! = - 1 ) {
// we lock the file for the other client
lockFile ( filepath , q , waked , taglia , lock , waiting ) ;
}
if ( pthread_mutex_unlock ( lock ) = = - 1 ) { // end ME
perror ( " unlock " ) ;
return ;
}
2022-04-04 22:31:14 +02:00
return ;
}
2022-03-31 22:26:44 +02:00
2022-04-08 21:32:52 +02:00
void removeFile ( char * filepath , queueT * q , long fd_c , taglia_t * taglia , pthread_mutex_t * lock , waiting_t * * waiting ) {
2022-04-10 20:51:43 +02:00
// messaggio da scrivere sul logfile
char tmp_buf [ LOGBUFSIZE ] ;
int n = 0 ;
size_t m = sizeof ( tmp_buf ) ;
if ( ! filepath | | ! q | | ! taglia | | ! lock | | ! waiting ) {
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una removeFile sul file \" %s \" e' terminata con errore. \n " , fd_c , filepath ) ;
errno = EINVAL ;
serror ( MESY , fd_c , taglia , tmp_buf ) ;
return ;
}
// cerco il file da eliminare
if ( ! searchFile ( q , filepath ) ) { // file e' assente
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una removeFile sul file \" %s \" ma risulta assente. \n " , fd_c , filepath ) ;
errno = ENOENT ;
serror ( MENT , fd_c , taglia , tmp_buf ) ;
return ;
}
if ( removeFileFromQueue ( q , filepath , fd_c ) = = - 1 ) {
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una removeFile sul file \" %s \" e' terminata con errore. \n " , fd_c , filepath ) ;
serror ( MENT , fd_c , taglia , tmp_buf ) ;
return ;
}
n + = snprintf ( tmp_buf + n , m - n , " Client %ld ha richiesto una removeFile sul file \" %s \" e' terminata con successo \n " , fd_c , filepath ) ;
sendMessage ( MEOK , fd_c , taglia , tmp_buf ) ;
// segnalo a un client in lista d'attesa che un file e' stato rimosso
if ( pthread_mutex_lock ( lock ) = = - 1 ) { // begin ME
perror ( " lock " ) ;
return ;
}
int waked = - 1 ;
waked = removeFirstWaiting ( waiting , filepath ) ;
if ( waked ! = - 1 ) {
// we lock the file for the other client
lockFile ( filepath , q , waked , taglia , lock , waiting ) ;
}
if ( pthread_mutex_unlock ( lock ) = = - 1 ) { // end ME
perror ( " unlock " ) ;
return ;
}
2022-04-04 22:31:14 +02:00
return ;
}
2022-03-31 22:26:44 +02:00
2022-04-10 20:51:43 +02:00
// -----------------------------------------------------------------------------
/* funzioni ausiliarie relative ai client in attesa di lock */
int addWaiting ( waiting_t * * waiting , char * filepath , int fd_c ) {
if ( ! waiting | | ! filepath ) {
errno = EINVAL ;
return - 1 ;
}
2022-03-31 22:26:44 +02:00
2022-04-10 20:51:43 +02:00
waiting_t * new = calloc ( 1 , sizeof ( waiting_t ) ) ;
if ( ! new ) {
perror ( " calloc " ) ;
return - 1 ;
}
new - > file = calloc ( MAXLENMESS , sizeof ( char ) ) ;
if ( ! new - > file ) {
perror ( " calloc " ) ;
free ( new ) ;
return - 1 ;
}
2022-03-18 20:49:28 +01:00
2022-04-10 20:51:43 +02:00
strncpy ( new - > file , filepath , strnlen ( filepath , MAXLENMESS - 1 ) + 1 ) ;
new - > fd = fd_c ;
new - > next = NULL ;
2022-03-18 20:49:28 +01:00
2022-04-10 20:51:43 +02:00
// se la lista è vuota
if ( * waiting = = NULL ) {
* waiting = new ;
return 0 ;
}
2022-03-18 20:49:28 +01:00
2022-04-10 20:51:43 +02:00
// se la lista ha almeno un elemento
waiting_t * tail = * waiting ;
while ( tail - > next ) {
tail = tail - > next ;
}
tail - > next = new ;
2022-03-18 20:49:28 +01:00
2022-04-08 21:32:52 +02:00
return 0 ;
2022-04-04 22:31:14 +02:00
}
2022-03-18 20:49:28 +01:00
2022-04-10 20:51:43 +02:00
// remove first who is waiting on the lock for the file
int removeFirstWaiting ( waiting_t * * waiting , char * filepath ) {
if ( ! waiting | | ! filepath ) {
errno = EINVAL ;
return - 1 ;
}
// none waiting
if ( * waiting = = NULL ) {
return - 1 ;
}
waiting_t * curr = * waiting ;
waiting_t * prec = NULL ;
long fd_c = - 1 ;
// first one waiting
if ( strcmp ( curr - > file , filepath ) = = 0 ) {
fd_c = curr - > fd ;
* waiting = curr - > next ;
free ( curr - > file ) ;
free ( curr ) ;
return fd_c ;
}
// more than one waiting
while ( curr - > next ) {
prec = curr ;
curr = curr - > next ;
if ( strcmp ( curr - > file , filepath ) = = 0 ) {
fd_c = curr - > fd ;
prec - > next = curr - > next ;
free ( curr - > file ) ;
free ( curr ) ;
2022-03-18 20:49:28 +01:00
2022-04-10 20:51:43 +02:00
return fd_c ;
}
}
return - 1 ;
}
// destroy waiting structure
2022-04-08 21:32:52 +02:00
void clearWaiting ( waiting_t * * waiting ) {
2022-04-10 20:51:43 +02:00
if ( ! waiting ) {
return ;
}
waiting_t * curr = * waiting ;
waiting_t * next = NULL ;
while ( curr ) {
next = curr - > next ;
2022-04-23 17:43:38 +02:00
if ( curr - > file )
free ( curr - > file ) ;
2022-04-10 20:51:43 +02:00
free ( curr ) ;
curr = next ;
}
* waiting = NULL ;
2022-04-04 22:31:14 +02:00
return ;
}