#define _POSIX_C_SOURCE 200809L #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 #define debughere(str) \ fprintf(stdout, "\nIn function: %s\n", __func__); \ fprintf(stdout, "\t%s\n", str); \ fflush(stdout); \ // ----------------------------------------------------------------------------- /* structs */ typedef struct files_s { char *filename; int locked; struct files_s *next; } files_t; typedef struct openfiles_s { int numOfFiles; files_t *f; // list of files int validwDir; // 1 if wDir is allocated char *wDir; // for files sent from the server after openFile int validrDir; // 1 if rDir is allocated 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 int64_t numfiles; // number of files if sent recivedFile_t *rf; // array of files } response_t; // ----------------------------------------------------------------------------- /* variabili globali */ static long fd_skt; // descriptor of the socket static char socketName[SOCKNAMEMAX] = ""; // name of the socket static openfiles_t *openedFiles = NULL; // ----------------------------------------------------------------------------- /* funzioni ausiliarie */ // closes every file opened by the client int closeEveryFile(); // closes and frees memory int removeOpenFile(const char *pathname); // adds element int addOpenFile(const char *pathname, const int flags); // checks if the file is open already int isOpen(const char *pathname, const int flags); // 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(const char *dirname, int n, recivedFile_t *rf); // frees memory inside response_t element void freeResponse(response_t *res); // creates the global variable int createOpenedFiles(void); // ----------------------------------------------------------------------------- int openConnection(const char* sockname, int msec, const struct timespec abstime) { if(!sockname){ errno = EINVAL; return -1; } if(!openedFiles) { if(createOpenedFiles()<0) { perror("createOpenedfiles"); return -1; } } struct sockaddr_un sa; struct timespec ts; ts.tv_sec = msec/1000; ts.tv_nsec = (msec % 1000) * 1000000; struct timeval t1, t2; // for gettimeofday long long start, end; // to calculate the time elapsed long long elapsedTime; // select socket strncpy(sa.sun_path, sockname, sizeof(sa.sun_path)-1); sa.sun_family = AF_UNIX; if ((fd_skt = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { errno = EINVAL; perror("socket"); return -1; } if(gettimeofday(&t1, NULL) != 0) { perror("gettimeofday"); return -1; } start = (long long) (t1.tv_sec * 1000000000 + t1.tv_usec * 1000); while (connect(fd_skt, (struct sockaddr*) &sa, sizeof(sa)) == -1) { gettimeofday(&t2, NULL); end = (long long) t2.tv_sec * 1000000000 + t2.tv_usec * 1000; elapsedTime = (end - start); // return if more time has elapsed than allowed if (elapsedTime > (abstime.tv_sec * 1000000000) + abstime.tv_nsec) { errno = ETIMEDOUT; return -1; } nanosleep(&ts, &ts); } strncpy(socketName, sockname, sizeof(socketName)-1); return 0; } int closeConnection(const char* sockname) { if (!sockname) { errno = EINVAL; return -1; } // if closing a different socket -> error if(strncmp(socketName, "", sizeof(socketName)) != 0 && strncmp(socketName, sockname, sizeof(socketName)) != 0) { errno = EINVAL; return -1; } // close every file if (closeEveryFile() == -1) { perror("closeEveryFile"); return -1; } // close socket if (close(fd_skt) == -1) { // return errno from close return -1; } memset(socketName, 0, SOCKNAMEMAX); return 0; } int openFile(const char* pathname, int flags) { 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, flags) == 1) { // already open return 0; } // invio al server la stringa "openFile|$(pathname)|$(flags)" int leng_flags = snprintf(NULL, 0, "%d", flags); long len = strlen("openFile")+1+strlen(pathname)+1+leng_flags+1; char *cmd = malloc(len); if(!cmd) { perror("malloc"); return -1; } memset(cmd, 0, len); snprintf(cmd, len, "openFile|%s|%d", pathname, flags); len = strnlen(cmd, len); // send cmd if (writen(fd_skt, &len, sizeof(long)) == -1) { // writen sets errno free(cmd); return -1; } 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, "\nIl server ha espulso i seguenti file:\n"); fflush(openedFiles->out); for(int i=0;inumfiles;++i) { fprintf(openedFiles->out, "\t%d) %s\n", i+1, res->rf[i].path); } } if(openedFiles->wDir) { if(openedFiles->print) { fprintf(openedFiles->out, "\tI file espulsi sono stati scritti nella cartella: %s\n", openedFiles->wDir); fflush(openedFiles->out); } 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, "\tI file espulsi non sono stati memorizzati su disco\n"); fflush(openedFiles->out); } } } if(addOpenFile(pathname, flags) == -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) { 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, 0) != 1) { // if it's not open => error errno = EPERM; return -1; } // invio al server la stringa readFile|$(pathname)" long 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); len = strnlen(cmd, len); // send cmd if (writen(fd_skt, &len, sizeof(long)) == -1) { // writen sets errno free(cmd); return -1; } 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\n", res->rf[0].path); printf("Di dimensione: %ld B\n", *size); fflush(openedFiles->out); } if(openedFiles->rDir) { if(openedFiles->print) { fprintf(openedFiles->out, "Il file letto e' stato scritto nella cartella: %s\n", openedFiles->rDir); fflush(openedFiles->out); } 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\n"); fflush(openedFiles->out); } } freeResponse(res); free(res); free(cmd); return 0; } int readNFiles(int N, const char* dirname) { if(!dirname) { 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; } // invio al server la stringa "readNFiles|$(N)" int lenght_n = snprintf(NULL, 0, "%d", N); long len = strlen("readNFiles")+1+lenght_n+1; char *cmd = malloc(len); if(!cmd) { perror("malloc"); return -1; } memset(cmd, 0, len); snprintf(cmd, len, "readNFiles|%d", N); len = strnlen(cmd, len); // send cmd if (writen(fd_skt, &len, sizeof(long)) == -1) { // writen sets errno free(cmd); return -1; } 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 N files // 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(openedFiles->print){ for(int i=0;inumfiles;++i) { fprintf(openedFiles->out, "%d) %s\n", i, res->rf[i].path); } fflush(openedFiles->out); } // save files to directory if(storeFilesInDirectory(dirname, res->numfiles, res->rf) == -1) { perror("storeFilesindirectory"); freeResponse(res); free(res); free(cmd); return -1; } int n = res->numfiles; freeResponse(res); free(res); free(cmd); return n; } int writeFile(const char* pathname, const char* dirname) { if(!pathname) { errno = EINVAL; return -1; } if(!openedFiles){ errno = EPROTO; return -1; } if (strcmp(openedFiles->createdAndLocked, pathname) != 0) { errno = EPERM; return -1; } if(openedFiles->createdAndLocked) free(openedFiles->createdAndLocked); openedFiles->createdAndLocked = NULL; if(strcmp(socketName, "") == 0) { errno = ENOTCONN; return -1; } // leggo il file da scrivere sul server int fdi = -1; size_t lung = 0; size_t incr = 0; size_t size = 0; if ((fdi = open(pathname, O_RDONLY)) == -1) { perror("open"); return -1; } // get file length struct stat sb; if (fstat(fdi, &sb) == -1) { perror("stat"); return -1; } lung = sb.st_size; void *content = malloc(lung); if(!content) { perror("malloc"); return -1; } // read file while ((incr = read(fdi, content, lung)) > 0) { size += incr; lung -= incr; } if (incr == -1) { free(content); return -1; } if (openedFiles->print) { fprintf(openedFiles->out, "Dimensione: %ldB ", size); fflush(openedFiles->out); } if (close(fdi) == -1) { perror("closing file"); free(content); return -1; } // invio al server la stringa "writeFile|$(pathname)|$(size)" int leng_size = snprintf(NULL, 0, "%zu", size); long len = strlen("writeFile")+1+strlen(pathname)+1+leng_size+1; char *cmd = calloc(len, sizeof(char)); if(!cmd) { perror("calloc"); free(content); return -1; } snprintf(cmd, len, "writeFile|%s|%zu", pathname, size); len = strnlen(cmd, len); // send cmd if (writen(fd_skt, &len, sizeof(long)) == -1) { // writen sets errno free(content); free(cmd); return -1; } if (writen(fd_skt, cmd, len) == -1) { // writen sets errno free(content); free(cmd); return -1; } // recive response response_t *res = calloc(1, sizeof(response_t)); if(!res){ perror("calloc"); free(content); free(cmd); return -1; } if(reciveData(res, 0) < 0) { // 0 because if we get a MEOK we don't expect files // errno is set by reciveData freeResponse(res); free(res); free(cmd); free(content); return -1; } if(res->meerrno != 0) { // errno from server freeResponse(res); errno = res->meerrno; free(res); free(cmd); free(content); 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:\n"); fflush(openedFiles->out); for(int i=0;inumfiles;++i) { fprintf(openedFiles->out, "%d) %s\n", i, res->rf[i].path); } } if(dirname) { if(storeFilesInDirectory(dirname, res->numfiles, res->rf) == -1) { perror("storeFilesindirectory"); freeResponse(res); free(res); free(content); free(cmd); return -1; } if(openedFiles->print) { fprintf(openedFiles->out, "I file espulsi sono stati scritti nella cartella: %s\n", dirname); fflush(openedFiles->out); } } else { if(openedFiles->print) { fprintf(openedFiles->out, "I file espulsi non sono stati memorizzati su disco\n"); fflush(openedFiles->out); } } } // send file to server if (writen(fd_skt, content, size) == -1) { // errno set by writen freeResponse(res); free(res); free(cmd); free(content); return -1; } // recive response if(reciveData(res, 0) < 0) { // 0 because if we get a MEOK we don't expect files // errno is set by reciveData freeResponse(res); free(res); free(cmd); free(content); return -1; } if(res->meerrno != 0) { // errno from server freeResponse(res); errno = res->meerrno; free(res); free(cmd); free(content); return -1; } freeResponse(res); free(res); free(cmd); free(content); return 0; } int appendToFile(const char* pathname, void* buf, size_t size, const char* dirname) { if(!pathname || !buf) { 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, 0) != 1) { errno = EPERM; return -1; } if (openedFiles->print) { fprintf(openedFiles->out, "Dimensione: %ld B\n", size); fflush(openedFiles->out); } // invio al server la stringa "appendToFile|$(pathname)|$(size)" long len = strlen("appendToFile")+1+strlen(pathname)+1+sizeof(size)+1; char *cmd = malloc(len); if(!cmd) { perror("malloc"); return -1; } memset(cmd, 0, len); snprintf(cmd, len, "appendToFile|%s|%zu", pathname, size); // send cmd if (writen(fd_skt, &len, sizeof(long)) == -1) { // writen sets errno free(cmd); return -1; } 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 don't expect files // 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:\n"); fflush(openedFiles->out); for(int i=0;inumfiles;++i) { fprintf(openedFiles->out, "%d) %s\n", i, res->rf[i].path); } } if(dirname) { if(storeFilesInDirectory(dirname, res->numfiles, res->rf) == -1) { perror("storeFilesindirectory"); freeResponse(res); free(res); free(cmd); return -1; } if(openedFiles->print) { fprintf(openedFiles->out, "I file espulsi sono stati scritti nella cartella: %s\n", dirname); fflush(openedFiles->out); } } else { if(openedFiles->print) { fprintf(openedFiles->out, "I file espulsi non sono stati memorizzati su disco\n"); fflush(openedFiles->out); } } } // send file to server if (writen(fd_skt, buf, size) == -1) { // errno set by writen freeResponse(res); free(res); free(cmd); return -1; } freeResponse(res); free(res); free(cmd); return 0; } int lockFile(const char* pathname) { 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, O_LOCK)){ // file is already locked return 0; } int existing = 0; if(isOpen(pathname, 0)){ // file is already open existing = 1; goto _unlockFile; } if (openFile(pathname, O_LOCK) == 0) // open the file with the lock return 0; if (errno == ENOENT) // file created but not locked goto _unlockFile; return -1; // errno != ENOENT _unlockFile: { // invio al server la stringa "lockFile|$(pathname)" long len = strlen("lockFile")+1+strlen(pathname)+1; char *cmd = malloc(len); if(!cmd) { perror("malloc"); return -1; } memset(cmd, 0, len); snprintf(cmd, len, "lockFile|%s", pathname); // send cmd if (writen(fd_skt, &len, sizeof(long)) == -1) { // writen sets errno free(cmd); return -1; } 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; } // 0 because if we get a MEOK we dont expect a file if(reciveData(res, 0) < 0) { // 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(!existing) { if(addOpenFile(pathname, O_LOCK) == -1) { perror("addOpenFile"); freeResponse(res); free(res); free(cmd); return -1; } } freeResponse(res); free(res); free(cmd); return 0; } } int unlockFile(const char* pathname) { 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, 0) != 1) { // not open or not locked errno = EPERM; return -1; } // invio al server la stringa "unlockFile|$(pathname)" long len = strlen("unlockFile")+1+strlen(pathname)+1; char *cmd = malloc(len); if(!cmd) { perror("malloc"); return -1; } memset(cmd, 0, len); snprintf(cmd, len, "unlockFile|%s", pathname); // send cmd if (writen(fd_skt, &len, sizeof(long)) == -1) { // writen sets errno free(cmd); return -1; } 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; } freeResponse(res); free(res); free(cmd); return 0; } int closeFile(const char *pathname) { 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, 0) != 1) { // not open errno = EPERM; return -1; } // invio al server la stringa "closeFile|$(pathname)" long len = strlen("closeFile")+1+strlen(pathname)+1; char *cmd = malloc(len); if(!cmd) { perror("malloc"); return -1; } memset(cmd, 0, len); snprintf(cmd, len, "closeFile|%s", pathname); // send cmd if (writen(fd_skt, &len, sizeof(long)) == -1) { // writen sets errno free(cmd); return -1; } 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 (removeOpenFile(pathname) == -1) { perror("removeOpenFile"); } else { openedFiles->numOfFiles--; } freeResponse(res); free(res); free(cmd); return 0; } int removeFile(const char* pathname) { 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, 0) != 1) { // not open errno = EPERM; return -1; } // invio al server la stringa "removeFile|$(pathname)" long len = strlen("removeFile")+1+strlen(pathname)+1; char *cmd = malloc(len); if(!cmd) { perror("malloc"); return -1; } memset(cmd, 0, len); snprintf(cmd, len, "removeFile|%s", pathname); // send cmd if (writen(fd_skt, &len, sizeof(long)) == -1) { // writen sets errno free(cmd); return -1; } 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 (removeOpenFile(pathname) == -1) { perror("removeOpenFile"); } else { openedFiles->numOfFiles--; } freeResponse(res); free(res); free(cmd); return 0; } // ----------------------------------------------------------------------------- int setDirectory(char* Dir, int rw) { if (!Dir) { errno = EINVAL; return -1; } if (rw == 1) { if(openedFiles->validwDir) { free(openedFiles->wDir); openedFiles->wDir = NULL; openedFiles->validwDir = 0; } if(strncmp(Dir, "/dev/null", strlen("/dev/null")+1) == 0) { return 0; } openedFiles->validwDir = 1; openedFiles->wDir = malloc(strlen(Dir)+1); strncpy(openedFiles->wDir, Dir, strlen(Dir)+1); } else { if(openedFiles->validrDir) { free(openedFiles->rDir); openedFiles->rDir = NULL; openedFiles->validrDir = 0; } if(strncmp(Dir, "/dev/null", strlen("/dev/null")+1) == 0) { return 0; } openedFiles->validrDir = 1; openedFiles->rDir = malloc(strlen(Dir)+1); strncpy(openedFiles->rDir, Dir, strlen(Dir)+1); } return 0; } void printInfo(int p, FILE *stream) { // 1 prints, 0 does not print if(!openedFiles) { if(createOpenedFiles()<0) { perror("createOpenedfiles"); return; } } openedFiles->print = (p)? 1: 0; openedFiles->out = stream; return; } // ----------------------------------------------------------------------------- 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(int64_t)); if(readnres<=0) // readn sets errno return -1; if(res->rf) free(res->rf); if(res->numfiles < 0) { errno = EINVAL; return -1; } 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; if(res->rf[i].filelen == 0) { res->rf[i].file = calloc(1, sizeof(char)); if(!res->rf[i].file){ perror("calloc"); return -1; } continue; } 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; if(res->rf[i].filelen == 0) { res->rf[i].file = calloc(1, sizeof(char)); if(!res->rf[i].file){ perror("calloc"); return -1; } continue; } 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(int64_t)); 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; // file has lenght 0 -> allocate memory but dont read if(res->rf[i].filelen == 0) { res->rf[i].file = calloc(1, sizeof(char)); if(!res->rf[i].file){ perror("calloc"); return -1; } continue; } 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(const char *dirname, int n, recivedFile_t *rf) { if(!dirname || strcmp(dirname, "")==0 || !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); strncat(basepath, "/", basepathlen); // for each file, create and write for(int i=0;inumfiles>0 && res->rf){ for(int i=0;inumfiles;++i){ if(res->rf[i].path) free(res->rf[i].path); res->rf[i].path = NULL; if(res->rf[i].file) free(res->rf[i].file); res->rf[i].file = NULL; } free(res->rf); } return; } int isOpen(const char *pathname, const int flags) { 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 && (tmp->locked || !(flags&O_LOCK))) return 1; tmp = tmp->next; } return 0; } int addOpenFile(const char *pathname, const int flags) { 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->locked = flags&O_LOCK; new->filename = calloc(len, sizeof(char)); if(!new->filename) { perror("calloc"); free(new); return -1; } strncpy(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(const char *pathname) { if(!pathname) { errno = EINVAL; return -1; } if(!openedFiles || !openedFiles->f || openedFiles->numOfFiles == 0) { errno = ENOENT; return -1; } files_t *tmp = openedFiles->f; // the element to remove is the first if(strcmp(tmp->filename, pathname) == 0) { openedFiles->f = tmp->next; free(tmp->filename); free(tmp); return 0; } files_t *prc = NULL; while(tmp->next) { prc = tmp; tmp = tmp->next; if(strcmp(tmp->filename, pathname) == 0) { prc->next = tmp->next; free(tmp->filename); free(tmp); return 0; } } // file not found errno = ENOENT; return -1; } int closeEveryFile() { if (openedFiles == NULL) return 0; if (openedFiles->numOfFiles > 0 && openedFiles->f != NULL) { files_t *tmp = openedFiles->f; files_t *prc = NULL; while(tmp){ prc = tmp; tmp = tmp->next; if(closeFile(prc->filename) != 0) { if(removeOpenFile(prc->filename) != 0) { perror("removeOpenfile"); } openedFiles->numOfFiles--; } } } if(openedFiles->createdAndLocked) { free(openedFiles->createdAndLocked); openedFiles->createdAndLocked = NULL; } if(openedFiles->validrDir) { free(openedFiles->rDir); openedFiles->validrDir = 0; openedFiles->rDir = NULL; } if(openedFiles->validwDir) { free(openedFiles->wDir); openedFiles->validwDir = 0; openedFiles->wDir = NULL; } free(openedFiles); openedFiles = NULL; return 0; } int createOpenedFiles(void) { openedFiles = calloc(1, sizeof(*openedFiles)); if(!openedFiles) { perror("calloc"); return -1; } openedFiles->f = NULL; openedFiles->numOfFiles = 0; openedFiles->createdAndLocked = NULL; openedFiles->validrDir = 0; openedFiles->rDir = NULL; openedFiles->validwDir = 0; openedFiles->wDir = NULL; openedFiles->print = 0; openedFiles->out = NULL; return 0; }