#define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include #include #include #include #include #include #include #include "api.h" #include "conn.h" #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 { char *filename; int locked; struct files_s *next; } files_t; typedef struct openfiles_s { int numOfFiles; files_t *f; /* list of files that are currently opened */ int validwDir; /* true if wDir is allocated */ char *wDir; /* for files sent from the server after openFile */ int validrDir; /* true 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; /* struct for the files sent from the server */ 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 sent by server */ int64_t numfiles; /* number of files if sent */ recivedFile_t *rf; /* array of files */ } response_t; // ----------------------------------------------------------------------------- // global variables static long fd_skt; /* descriptor of the socket */ static char socketName[SOCKNAMEMAX] = ""; /* name of the socket */ static openfiles_t *openedFiles = NULL; // ----------------------------------------------------------------------------- // helper functions /* closes every file opened by the client */ int closeEveryFile(); /* closes and frees memory */ int removeOpenFile(const char *); /* adds element */ int addOpenFile(const char *, const int); /* checks if the file is open already */ int isOpen(const char *, const int); /* reads everything the server sent into the variable passed to the function * expected == 1 if a file should be sent (if no server errors occurs) */ int reciveData(response_t *, int expected); /* saves the files in the specified directory */ int storeFilesInDirectory(const char *, int n, recivedFile_t *); /* frees memory inside response_t element */ void freeResponse(response_t *); /* initiates the global variables */ int createOpenedFiles(); // ----------------------------------------------------------------------------- int openConnection(const char* sockname, int msec, const struct timespec abstime) { if(!sockname){ errno = EINVAL; return -1; } if(!openedFiles) { if(createOpenedFiles()<0) { perror("openConnection: 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("openConnection: socket"); return -1; } if(gettimeofday(&t1, NULL) != 0) { perror("openConnection: 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("closeConnection: 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; } /* sent to server the string "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("openFile: 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("openFile: calloc"); free(cmd); return -1; } /* reciveData(, 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(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("openFile: 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("openFile: 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("openFile: 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; } /* send to server the string readFile|$(pathname)" */ long len = strlen("readFile")+1+strlen(pathname)+1; char *cmd = malloc(len); if(!cmd) { perror("readFile: 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("readFile: calloc"); free(cmd); return -1; } /* reciveData(, 1) because if we get a MEOK we expect a file */ if(reciveData(res, 1) < 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; } /* 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("readFile: 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("readFile: 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; } /* send to server the string "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("readNFiles: 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("readNFiles: calloc"); free(cmd); return -1; } /* reciveData(, 1) because if we get a MEOK we expect N files */ if(reciveData(res, 1) < 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(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("readNFiles: 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; } /* read the file that needs to be sent to the server */ int fdi = -1; size_t lung = 0; size_t incr = 0; size_t size = 0; if ((fdi = open(pathname, O_RDONLY)) == -1) { perror("writeFile: open"); return -1; } /* get file length */ struct stat sb; if (fstat(fdi, &sb) == -1) { perror("writeFile: fstat"); return -1; } lung = sb.st_size; void *content = malloc(lung); if(!content) { perror("writeFile: 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("writeFile: close"); free(content); return -1; } /* send to server the string "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("writeFile: 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("writeFile: calloc"); free(content); free(cmd); return -1; } /* reciveData(, 0) because if we get a MEOK we don't expect files */ if(reciveData(res, 0) < 0) { /* 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("writeFile: 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; } /* reciveData(, 0) because if we get a MEOK we don't expect files */ if(reciveData(res, 0) < 0) { /* 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); } /* send to server the string "appendToFile|$(pathname)|$(size)" */ int leng_size = snprintf(NULL, 0, "%zu", size); long len = strlen("appendToFile")+1+strlen(pathname)+1+leng_size+1; char *cmd = malloc(len); if(!cmd) { perror("appendToFile: 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("appendToFile: calloc"); free(cmd); return -1; } /* reciveData(, 0) because if we get a MEOK we don't expect files */ 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(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("appendToFile: 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: { /* send to server the string "lockFile|$(pathname)" */ long len = strlen("lockFile")+1+strlen(pathname)+1; char *cmd = malloc(len); if(!cmd) { perror("lockFile: 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("lockFile: calloc"); free(cmd); return -1; } /* reciveData(, 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("lockFile: 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; } /* send to server the string "unlockFile|$(pathname)" */ long len = strlen("unlockFile")+1+strlen(pathname)+1; char *cmd = malloc(len); if(!cmd) { perror("unlockFile: 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("unlockFile: calloc"); free(cmd); return -1; } /* reciveData(, 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; } 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("closeFile: 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("closeFile: calloc"); free(cmd); return -1; } /* reciveData(, 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 (removeOpenFile(pathname) == -1) { perror("closeFile: 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; } /* send to server the string "removeFile|$(pathname)" */ long len = strlen("removeFile")+1+strlen(pathname)+1; char *cmd = malloc(len); if(!cmd) { perror("removeFile: 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("removeFile: calloc"); free(cmd); return -1; } /* reciveData(, 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 (removeOpenFile(pathname) == -1) { perror("removeFile: 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("printInfo: createOpenedfiles"); return; } } openedFiles->print = (p)? 1: 0; openedFiles->out = stream; return; } // ----------------------------------------------------------------------------- // helper functions 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("reciveData: 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("reciveData: 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("reciveData: calloc"); return -1; } continue; } res->rf[i].file = calloc(res->rf[i].filelen, sizeof(char)); if(!res->rf[i].file){ perror("reciveData: 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("reciveData: 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("reciveData: 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("reciveData: calloc"); return -1; } continue; } res->rf[i].file = calloc(res->rf[i].filelen, sizeof(char)); if(!res->rf[i].file){ perror("reciveData: 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("reciveData: 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("reciveData: 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("reciveData: calloc"); return -1; } continue; } res->rf[i].file = calloc(res->rf[i].filelen, sizeof(char)); if(!res->rf[i].file){ perror("reciveData: 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("storeFilesInDirectory: 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("addOpenFile: malloc"); return -1; } size_t len = strlen(pathname)+1; new->locked = flags&O_LOCK; new->filename = calloc(len, sizeof(char)); if(!new->filename) { perror("addOpenFile: 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("closeEveryFile: 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() { openedFiles = calloc(1, sizeof(*openedFiles)); if(!openedFiles) { perror("createOpenedFiles: 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; }