diff --git a/lib/api/api.c b/lib/api/api.c index 579c007..61b306c 100644 --- a/lib/api/api.c +++ b/lib/api/api.c @@ -1,16 +1,35 @@ -#include #include +#include #include -#include #include +#include #include -#include +#include #include +#include +#include #include +#include #define SOCKNAMEMAX 256 // should be at least 108 + +#define MEOK "20" //OK +// #define ME "21" // not used +// #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 + // ----------------------------------------------------------------------------- /* structs */ typedef struct files_s { @@ -20,13 +39,29 @@ typedef struct files_s { typedef struct openfiles_s { int numOfFiles; - files_t *f; + files_t *f; // list of files char *wDir; // for files sent from the server after openFile char *rDir; // for files read from the server + char *createdAndLocked; // path of the last file that was created and locked int print; // whether to print FILE *out; // where to print } openfiles_t; + +typedef struct recivedFile_s { + int64_t pathlen; + char *path; + int64_t filelen; + char *file; +} recivedFile_t; + +typedef struct response_s { + char ME[2]; // response + int meerrno; // errno if sent + int numfiles; // number of files if sent + recivedFile_t *rf; // array of files +} response_t; + // ----------------------------------------------------------------------------- /* variabili globali */ static int fd_skt; // descriptor of the socket @@ -39,10 +74,18 @@ static openfiles_t *openedFiles = NULL; // closes every file opened by the client int closeEveryFile(); // closes and frees memory -int removeOpenFile(const char *pathname); - - - +int removeOpenFile(char *pathname); +// adds element +int addOpenFile(const char *pathname); +// checks if the file is open already +int isOpen(const char *pathname); +// reads everything the server sent into the variable passed to the function +// expected is 1 if a file could be sent (if no server errors occurs) +int reciveData(response_t *res, int expected); +// saves the files in the specified directory +int storeFilesInDirectory(char *dirname, int n, recivedFile_t *rf); +// frees memory inside response_t element +void freeResponse(response_t *res); @@ -62,6 +105,7 @@ int openConnection(const char* sockname, int msec, const struct timespec abstime } openedFiles->f = NULL; openedFiles->numOfFiles = 0; + openedFiles->createdAndLocked = NULL; openedFiles->rDir = NULL; openedFiles->wDir = NULL; openedFiles->print = 0; @@ -130,6 +174,8 @@ int closeConnection(const char* sockname) { memset(socketName, 0, SOCKNAMEMAX); if (openedFiles) { + if(openedFiles->createdAndLocked) + free(openedFiles->createdAndLocked); if(openedFiles->wDir) free(openedFiles->wDir); if(openedFiles->rDir) @@ -141,11 +187,232 @@ int closeConnection(const char* sockname) { } int openFile(const char* pathname, int flags) { - return 1; + if(!pathname){ + errno = EINVAL; + return -1; + } + if(!openedFiles){ + errno = EPROTO; + return -1; + } + if(openedFiles->createdAndLocked) + free(openedFiles->createdAndLocked); + openedFiles->createdAndLocked = NULL; + + if(strcmp(socketName, "") == 0) { + errno = ENOTCONN; + return -1; + } + if(isOpen(pathname)) { // already open + return -1; + } + + // invio al server la stringa "openFile|$(pathname)|$(flags)" + size_t len = strlen("openFile")+1+strlen(pathname)+1+sizeof(flags)+1; + char *cmd = malloc(len); + if(!cmd) { + perror("malloc"); + return -1; + } + memset(cmd, 0, len); + snprintf(cmd, len, "openFile|%s|%d", pathname, flags); + + // send cmd + if (writen(fd_skt, cmd, len) == -1) { + // writen sets errno + free(cmd); + return -1; + } + + // recive response + response_t *res = calloc(1, sizeof(response_t)); + if(!res){ + perror("calloc"); + free(cmd); + return -1; + } + if(reciveData(res, 0) < 0) { // 0 because if we get a MEOK we dont expect a file + // errno is set by reciveData + freeResponse(res); + free(res); + free(cmd); + return -1; + } + if(res->meerrno != 0) { + // errno from server + freeResponse(res); + errno = res->meerrno; + free(res); + free(cmd); + return -1; + } + if(strncmp(res->ME, MEFP, sizeof(res->ME)) == 0) { + // some files were purged + if(openedFiles->print){ + fprintf(openedFiles->out, "Il server ha espulso i seguenti file:"); + fflush(stdout); + for(int i=0;inumfiles;++i) { + fprintf(openedFiles->out, "%d) %s", i, res->rf[i].path); + } + } + if(openedFiles->wDir) { + if(openedFiles->print) { + fprintf(openedFiles->out, "I file espulsi sono stati scritti nella cartella: %s", openedFiles->wDir); + fflush(stdout); + } + if(storeFilesInDirectory(openedFiles->wDir, res->numfiles, res->rf) == -1) { + perror("storeFilesindirectory"); + freeResponse(res); + free(res); + free(cmd); + return -1; + } + } else { + if(openedFiles->print) { + fprintf(openedFiles->out, "I file espulsi non sono stati memorizzati su disco"); + fflush(stdout); + } + } + } + + if(addOpenFile(pathname) == -1) { + perror("addOpenFile"); + return -1; + } + + if(flags == (O_CREATE | O_LOCK)) { + if(openedFiles->createdAndLocked) + free(openedFiles->createdAndLocked); + openedFiles->createdAndLocked = calloc(strlen(pathname)+1, sizeof(char)); + if(!openedFiles->createdAndLocked) { + perror("calloc"); + freeResponse(res); + free(res); + free(cmd); + return -1; + } + strcpy(openedFiles->createdAndLocked, pathname); + } + + freeResponse(res); + free(res); + + free(cmd); + return 0; } int readFile(const char* pathname, void** buf, size_t* size) { - return 1; + if(!pathname) { + errno = EINVAL; + return -1; + } + if(!openedFiles){ + errno = EPROTO; + return -1; + } + if(openedFiles->createdAndLocked) + free(openedFiles->createdAndLocked); + openedFiles->createdAndLocked = NULL; + + if(strcmp(socketName, "") == 0) { + errno = ENOTCONN; + return -1; + } + + if (isOpen(pathname) != 1) { // if it's not open => error + errno = EPERM; + return -1; + } + + // invio al server la stringa readFile|$(pathname)" + size_t len = strlen("readFile")+1+strlen(pathname)+1; + char *cmd = malloc(len); + if(!cmd) { + perror("malloc"); + return -1; + } + memset(cmd, 0, len); + snprintf(cmd, len, "readFile|%s", pathname); + + // send cmd + if (writen(fd_skt, cmd, len) == -1) { + // writen sets errno + free(cmd); + return -1; + } + + // recive response + response_t *res = calloc(1, sizeof(response_t)); + if(!res){ + perror("calloc"); + free(cmd); + return -1; + } + if(reciveData(res, 1) < 0) { // 1 because if we get a MEOK we expect a file + // errno is set by reciveData + freeResponse(res); + free(res); + free(cmd); + return -1; + } + if(res->meerrno != 0) { + // errno from server + freeResponse(res); + errno = res->meerrno; + free(res); + free(cmd); + return -1; + } + + // no errors from server + if(res->numfiles != 1) { + freeResponse(res); + free(res); + free(cmd); + errno = EMSGSIZE; + return -1; + } + *size = (size_t) res->rf[0].filelen; + *buf = malloc(*size); + if(!*buf) { + freeResponse(res); + free(res); + free(cmd); + perror("malloc"); + return -1; + } + memcpy(*buf, res->rf[0].file, *size); + if(openedFiles->print) { + printf("Letto il file: %s", res->rf[0].path); + printf("Di dimensione: %ld B\n", *size); + fflush(stdout); + } + if(openedFiles->rDir) { + if(openedFiles->print) { + fprintf(openedFiles->out, "Il file letto e' stato scritto nella cartella: %s", openedFiles->rDir); + fflush(stdout); + } + if(storeFilesInDirectory(openedFiles->rDir, 1, res->rf) == -1) { + perror("storeFilesindirectory"); + freeResponse(res); + free(res); + free(cmd); + return -1; + } + } else { + if(openedFiles->print) { + fprintf(openedFiles->out, "Il file letto non รจ stato memorizzato su disco"); + fflush(stdout); + } + } + + + freeResponse(res); + free(res); + + free(cmd); + + return 0; } int readNFiles(int N, const char* dirname) { @@ -191,7 +458,387 @@ void printInfo(int p, FILE *stream) { // ----------------------------------------------------------------------------- -int removeOpenFile(const char *pathname) { +int reciveData(response_t *res, int expected) { + if(!res) { + errno = EINVAL; + return -1; + } + + int readnres; + readnres = readn(fd_skt, res->ME, sizeof(res->ME)); + if(readnres <= 0) { + // readn sets errno + return -1; + } + + if(expected == 0) // no file expected + goto _nofile; + + + // file is expected + if(strncmp(res->ME, MEOK, sizeof(res->ME))==0){ + // ok response + res->meerrno = 0; + // get number of files sent + readnres = readn(fd_skt, &res->numfiles, sizeof(int)); + if(readnres<=0) // readn sets errno + return -1; + + if(res->rf) + free(res->rf); + res->rf = calloc(res->numfiles, sizeof(recivedFile_t)); + if(!res->rf){ + perror("calloc"); + return -1; + } + // get files + for(int i=0;inumfiles;++i) { + // read path + readnres = readn(fd_skt, &res->rf[i].pathlen, sizeof(int64_t)); + if(readnres<=0) // readn sets errno + return -1; + res->rf[i].path = calloc(res->rf[i].pathlen, sizeof(char)); + if(!res->rf[i].path){ + perror("calloc"); + return -1; + } + readnres = readn(fd_skt, res->rf[i].path, res->rf[i].pathlen); + if(readnres<=0) // readn sets errno + return -1; + + // we replace '/' char with '-' + for(int j=0;jrf[i].pathlen; ++j){ + if(res->rf[i].path[j] == '/') + res->rf[i].path[j] = '-'; + } + + // read file + readnres = readn(fd_skt, &res->rf[i].filelen, sizeof(int64_t)); + if(readnres<=0) // readn sets errno + return -1; + res->rf[i].file = calloc(res->rf[i].filelen, sizeof(char)); + if(!res->rf[i].file){ + perror("calloc"); + return -1; + } + readnres = readn(fd_skt, res->rf[i].file, res->rf[i].filelen); + if(readnres<=0) // readn sets errno + return -1; + } + return 0; + } + if(strncmp(res->ME, MEFP, sizeof(res->ME))==0){ + // file purged + res->meerrno = 0; + // get number of files sent + readnres = readn(fd_skt, &res->numfiles, sizeof(int)); + if(readnres<=0) // readn sets errno + return -1; + + if(res->rf) + free(res->rf); + res->rf = calloc(res->numfiles, sizeof(recivedFile_t)); + if(!res->rf){ + perror("calloc"); + return -1; + } + // get files + for(int i=0;inumfiles;++i) { + // read path + readnres = readn(fd_skt, &res->rf[i].pathlen, sizeof(int64_t)); + if(readnres<=0) // readn sets errno + return -1; + res->rf[i].path = calloc(res->rf[i].pathlen, sizeof(char)); + if(!res->rf[i].path){ + perror("calloc"); + return -1; + } + readnres = readn(fd_skt, res->rf[i].path, res->rf[i].pathlen); + if(readnres<=0) // readn sets errno + return -1; + + // we replace '/' char with '-' + for(int j=0;jrf[i].pathlen; ++j){ + if(res->rf[i].path[j] == '/') + res->rf[i].path[j] = '-'; + } + + // read file + readnres = readn(fd_skt, &res->rf[i].filelen, sizeof(int64_t)); + if(readnres<=0) // readn sets errno + return -1; + res->rf[i].file = calloc(res->rf[i].filelen, sizeof(char)); + if(!res->rf[i].file){ + perror("calloc"); + return -1; + } + readnres = readn(fd_skt, res->rf[i].file, res->rf[i].filelen); + if(readnres<=0) // readn sets errno + return -1; + } + return 0; + } + if(strncmp(res->ME, MESD, sizeof(res->ME))==0){ + // server shutting down + readnres = readn(fd_skt, &res->meerrno, sizeof(errno)); + if(readnres <= 0)// readn sets errno + return -1; + return 0; + } + if(strncmp(res->ME, MENT, sizeof(res->ME))==0){ + // requested file action not taken + readnres = readn(fd_skt, &res->meerrno, sizeof(errno)); + if(readnres <= 0)// readn sets errno + return -1; + return 0; + } + if(strncmp(res->ME, MESY, sizeof(res->ME))==0){ + // syntax error + readnres = readn(fd_skt, &res->meerrno, sizeof(errno)); + if(readnres <= 0)// readn sets errno + return -1; + return 0; + } + if(strncmp(res->ME, MESE, sizeof(res->ME))==0){ + // server error + readnres = readn(fd_skt, &res->meerrno, sizeof(errno)); + if(readnres <= 0)// readn sets errno + return -1; + return 0; + } + + errno = ENOPROTOOPT; + return -2; + +_nofile: + res->numfiles = 0; + if(res->rf) + free(res->rf); + res->rf = NULL; + + + if(strncmp(res->ME, MEOK, sizeof(res->ME))==0){ + // simple ok response + res->meerrno = 0; + return 0; + } + if(strncmp(res->ME, MEFP, sizeof(res->ME))==0){ + // file purged + res->meerrno = 0; + // get number of files sent + readnres = readn(fd_skt, &res->numfiles, sizeof(int)); + if(readnres<=0) // readn sets errno + return -1; + + if(res->rf) + free(res->rf); + res->rf = calloc(res->numfiles, sizeof(recivedFile_t)); + if(!res->rf){ + perror("calloc"); + return -1; + } + // get files + for(int i=0;inumfiles;++i) { + // read path + readnres = readn(fd_skt, &res->rf[i].pathlen, sizeof(int64_t)); + if(readnres<=0) // readn sets errno + return -1; + res->rf[i].path = calloc(res->rf[i].pathlen, sizeof(char)); + if(!res->rf[i].path){ + perror("calloc"); + return -1; + } + readnres = readn(fd_skt, res->rf[i].path, res->rf[i].pathlen); + if(readnres<=0) // readn sets errno + return -1; + + // we replace '/' char with '-' + for(int j=0;jrf[i].pathlen; ++j){ + if(res->rf[i].path[j] == '/') + res->rf[i].path[j] = '-'; + } + + // read file + readnres = readn(fd_skt, &res->rf[i].filelen, sizeof(int64_t)); + if(readnres<=0) // readn sets errno + return -1; + res->rf[i].file = calloc(res->rf[i].filelen, sizeof(char)); + if(!res->rf[i].file){ + perror("calloc"); + return -1; + } + readnres = readn(fd_skt, res->rf[i].file, res->rf[i].filelen); + if(readnres<=0) // readn sets errno + return -1; + } + return 0; + } + if(strncmp(res->ME, MESD, sizeof(res->ME))==0){ + // server shutting down + readnres = readn(fd_skt, &res->meerrno, sizeof(errno)); + if(readnres <= 0)// readn sets errno + return -1; + return 0; + } + if(strncmp(res->ME, MENT, sizeof(res->ME))==0){ + // requested file action not taken + readnres = readn(fd_skt, &res->meerrno, sizeof(errno)); + if(readnres <= 0)// readn sets errno + return -1; + return 0; + } + if(strncmp(res->ME, MESY, sizeof(res->ME))==0){ + // syntax error + readnres = readn(fd_skt, &res->meerrno, sizeof(errno)); + if(readnres <= 0)// readn sets errno + return -1; + return 0; + } + if(strncmp(res->ME, MESE, sizeof(res->ME))==0){ + // server error + readnres = readn(fd_skt, &res->meerrno, sizeof(errno)); + if(readnres <= 0)// readn sets errno + return -1; + return 0; + } + + errno = ENOPROTOOPT; + return -2; +} + +int storeFilesInDirectory(char *dirname, int n, recivedFile_t *rf) { + if(!dirname || strcmp(dirname, "") || !rf || n<0) { + errno = EINVAL; + return -1; + } + + // create directory + if(mkdir(dirname, 0777) == -1) { + if(errno != EEXIST) { // unknown error + return -1; + } + } + + size_t basepathlen = strlen(dirname)+1+1; // +1 for '/' and +1 for '\0' + char *basepath = calloc(basepathlen, sizeof(char)); + if(!basepath) { + perror("calloc"); + return -1; + } + strcpy(basepath, dirname); + strlcat(basepath, "/", basepathlen); + + // for each file, create and write + for(int i=0;inumfiles>0 && res->rf){ + for(int i=0;inumfiles;++i){ + free(res->rf[i].path); + free(res->rf[i].file); + } + free(res->rf); + } + if(res->rf) + free(res->rf); + return; +} + +int isOpen(const char *pathname) { + if(!pathname) { + errno = EINVAL; + return -1; + } + + if (openedFiles == NULL || openedFiles->f == NULL || openedFiles->numOfFiles == 0) { + return 0; + } + + files_t *tmp = openedFiles->f; + while(tmp) { + if(strcmp(tmp->filename, pathname) == 0) + return 1; + tmp = tmp->next; + } + + return 0; +} + +int addOpenFile(const char *pathname) { + if(!pathname) { + errno = EINVAL; + return -1; + } + + files_t *new = malloc(sizeof(files_t)); + if(!new) { + perror("malloc"); + return -1; + } + + size_t len = strlen(pathname)+1; + new->filename = calloc(len, sizeof(char)); + if(!new->filename) { + perror("calloc"); + free(new); + return -1; + } + + strlcpy(new->filename, pathname, len); + new->next = NULL; + + if(openedFiles->f == NULL) { + openedFiles->f = new; + openedFiles->numOfFiles = 1; + return 0; + } + + files_t *tail = openedFiles->f; + while(tail->next) { + tail = tail->next; + } + tail->next = new; + openedFiles->numOfFiles++; + return 0; +} + +int removeOpenFile(char *pathname) { if(!pathname) { errno = EINVAL; return -1; diff --git a/lib/threadpool/apiFile.c b/lib/threadpool/apiFile.c index 120105f..efdb61a 100644 --- a/lib/threadpool/apiFile.c +++ b/lib/threadpool/apiFile.c @@ -12,7 +12,7 @@ #define LOGBUFSIZE 2048 #define MEOK "20" //OK -#define MEHE "21" // help message +// #define ME "21" // not used // #define ME "22" // not used #define MEFP "25" // file purged @@ -131,6 +131,12 @@ void sendMessageFile(char *m, fileT *f, long fd_c, taglia_t *taglia, char *mlog) goto _sendMF_cleanup; } + int n = 1; + if(writen(fd_c, &n, sizeof(n)) < 0) { + perror("writen"); + goto _sendMF_cleanup; + } + if(sendFile(f, fd_c, taglia) < 0) { perror("sendFile"); goto _sendMF_cleanup; @@ -165,6 +171,11 @@ void sendMessageFileN(char *m, fileT **f, int n, long fd_c, taglia_t *taglia, ch goto _sendMFN_cleanup; } + if(write(fd_c, &n, sizeof(n)) < 0) { + perror("writen"); + goto _sendMFN_cleanup; + } + for(int i=0; i